Added unit tests for exit and symbol-function and refactored some code
This commit is contained in:
parent
ea8acd423f
commit
1f0d312e7e
|
@ -1,61 +1,50 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import error.LispException;
|
||||||
import function.*;
|
import function.*;
|
||||||
import function.builtin.cons.LENGTH;
|
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>SYMBOL_FUNCTION</code> represents the SYMBOL-FUNCTION function in
|
|
||||||
* Lisp.
|
|
||||||
*/
|
|
||||||
public class SYMBOL_FUNCTION extends LispFunction {
|
public class SYMBOL_FUNCTION extends LispFunction {
|
||||||
|
|
||||||
// The number of arguments that SYMBOL-FUNCTION takes.
|
private ArgumentValidator argumentValidator;
|
||||||
private static final int NUM_ARGS = 1;
|
|
||||||
|
|
||||||
public SExpression call(Cons argList) {
|
public SYMBOL_FUNCTION() {
|
||||||
// retrieve the number of arguments passed to SYMBOL-FUNCTION
|
this.argumentValidator = new ArgumentValidator("SYMBOL-FUNCTION");
|
||||||
int argListLength = LENGTH.getLength(argList);
|
this.argumentValidator.setExactNumberOfArguments(1);
|
||||||
|
this.argumentValidator.setEveryArgumentExpectedType(Symbol.class);
|
||||||
|
}
|
||||||
|
|
||||||
// make sure we have received the proper number of arguments
|
public SExpression call(Cons argumentList) {
|
||||||
if (argListLength != NUM_ARGS) {
|
argumentValidator.validate(argumentList);
|
||||||
Cons originalSExpr = new Cons(new Symbol("SYMBOL-FUNCTION"),
|
|
||||||
argList);
|
|
||||||
String errMsg = "too " +
|
|
||||||
((argListLength > NUM_ARGS) ? "many" : "few") +
|
|
||||||
" arguments given to SYMBOL-FUNCTION: " +
|
|
||||||
originalSExpr;
|
|
||||||
|
|
||||||
throw new RuntimeException(errMsg);
|
SExpression symbol = argumentList.getCar();
|
||||||
|
LispFunction function = EVAL.lookupFunction(symbol.toString());
|
||||||
|
|
||||||
|
if (function != null) {
|
||||||
|
if (function instanceof UserDefinedFunction)
|
||||||
|
return ((UserDefinedFunction) function).getLambdaExpression();
|
||||||
|
|
||||||
|
return new Symbol(MessageFormat.format("#<SYSTEM-FUNCTION {0}>", symbol.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SExpression arg = argList.getCar();
|
throw new UndefinedSymbolFunctionException(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
// make sure the argument is a symbol
|
public static class UndefinedSymbolFunctionException extends LispException {
|
||||||
if (arg.symbolp()) {
|
|
||||||
LispFunction function = EVAL.lookupFunction(arg.toString());
|
|
||||||
|
|
||||||
// make sure the function actually exists
|
private static final long serialVersionUID = 1L;
|
||||||
if (function != null) {
|
private SExpression function;
|
||||||
if (function instanceof UserDefinedFunction) {
|
|
||||||
// this is a user-defined function
|
|
||||||
|
|
||||||
UserDefinedFunction udFunction = (UserDefinedFunction) function;
|
public UndefinedSymbolFunctionException(SExpression function) {
|
||||||
|
this.function = function;
|
||||||
return udFunction.getLambdaExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is a built-in function
|
|
||||||
|
|
||||||
return new Symbol("SUBR-" + arg.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException("SYMBOL-FUNCTION: undefined function " +
|
|
||||||
arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException("SYMBOL-FUNCTION: " + arg +
|
@Override
|
||||||
" is not a symbol");
|
public String getMessage() {
|
||||||
|
return MessageFormat.format("SYMBOL-FUNCTION: undefined function: {0}", function);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package function.builtin;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import environment.Environment;
|
||||||
|
import function.ArgumentValidator.TooManyArgumentsException;
|
||||||
|
|
||||||
|
public class EXITTester {
|
||||||
|
|
||||||
|
private static final String TERMINATED = "terminated";
|
||||||
|
private Set<String> indicatorSet;
|
||||||
|
|
||||||
|
private void assertTerminated() {
|
||||||
|
assertTrue(indicatorSet.contains(TERMINATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNotTerminated() {
|
||||||
|
assertFalse(indicatorSet.contains(TERMINATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
indicatorSet = new HashSet<>();
|
||||||
|
Environment.getInstance().setTerminationFunction(() -> indicatorSet.add(TERMINATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exitWorks() {
|
||||||
|
evaluateString("(exit)");
|
||||||
|
assertTerminated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exitNotCalled_IndicatorSetIsClean() {
|
||||||
|
assertNotTerminated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void testExitWithTooManyArguments() {
|
||||||
|
evaluateString("(exit 1)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package function.builtin;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import function.ArgumentValidator.*;
|
||||||
|
import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException;
|
||||||
|
import sexpression.Nil;
|
||||||
|
|
||||||
|
public class SYMBOL_FUNCTIONTester {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSymbolFunction_BuiltinFunction() {
|
||||||
|
String input = "(symbol-function '+)";
|
||||||
|
|
||||||
|
assertEquals("#<SYSTEM-FUNCTION +>", evaluateString(input).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSymbolFunction_UserDefinedFunction() {
|
||||||
|
String defineUserFunction = "(defun y (n m) (+ n m))";
|
||||||
|
String input = "(symbol-function 'y)";
|
||||||
|
|
||||||
|
evaluateString(defineUserFunction);
|
||||||
|
assertEquals("(Y (N M) (+ N M))", evaluateString(input).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = RuntimeException.class)
|
||||||
|
public void testSymbolFunction_NonFunction() {
|
||||||
|
String input = "(symbol-function 'a)";
|
||||||
|
|
||||||
|
evaluateString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
public void testSymbolFunctionWithBadArgumentType() {
|
||||||
|
evaluateString("(symbol-function 2)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void testSymbolFunctionWithTooManyArguments() {
|
||||||
|
evaluateString("(symbol-function 'a 'b)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void testSymbolFunctionWithTooFewArguments() {
|
||||||
|
evaluateString("(symbol-function)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void undefinedSymbolFunctionException_HasMessageText() {
|
||||||
|
UndefinedSymbolFunctionException e = new UndefinedSymbolFunctionException(Nil.getInstance());
|
||||||
|
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue