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;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
import function.*;
|
||||
import function.builtin.cons.LENGTH;
|
||||
import sexpression.*;
|
||||
|
||||
/**
|
||||
* <code>SYMBOL_FUNCTION</code> represents the SYMBOL-FUNCTION function in
|
||||
* Lisp.
|
||||
*/
|
||||
public class SYMBOL_FUNCTION extends LispFunction {
|
||||
|
||||
// The number of arguments that SYMBOL-FUNCTION takes.
|
||||
private static final int NUM_ARGS = 1;
|
||||
private ArgumentValidator argumentValidator;
|
||||
|
||||
public SExpression call(Cons argList) {
|
||||
// retrieve the number of arguments passed to SYMBOL-FUNCTION
|
||||
int argListLength = LENGTH.getLength(argList);
|
||||
public SYMBOL_FUNCTION() {
|
||||
this.argumentValidator = new ArgumentValidator("SYMBOL-FUNCTION");
|
||||
this.argumentValidator.setExactNumberOfArguments(1);
|
||||
this.argumentValidator.setEveryArgumentExpectedType(Symbol.class);
|
||||
}
|
||||
|
||||
// make sure we have received the proper number of arguments
|
||||
if (argListLength != NUM_ARGS) {
|
||||
Cons originalSExpr = new Cons(new Symbol("SYMBOL-FUNCTION"),
|
||||
argList);
|
||||
String errMsg = "too " +
|
||||
((argListLength > NUM_ARGS) ? "many" : "few") +
|
||||
" arguments given to SYMBOL-FUNCTION: " +
|
||||
originalSExpr;
|
||||
public SExpression call(Cons argumentList) {
|
||||
argumentValidator.validate(argumentList);
|
||||
|
||||
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
|
||||
if (arg.symbolp()) {
|
||||
LispFunction function = EVAL.lookupFunction(arg.toString());
|
||||
public static class UndefinedSymbolFunctionException extends LispException {
|
||||
|
||||
// make sure the function actually exists
|
||||
if (function != null) {
|
||||
if (function instanceof UserDefinedFunction) {
|
||||
// this is a user-defined function
|
||||
private static final long serialVersionUID = 1L;
|
||||
private SExpression function;
|
||||
|
||||
UserDefinedFunction udFunction = (UserDefinedFunction) function;
|
||||
|
||||
return udFunction.getLambdaExpression();
|
||||
}
|
||||
|
||||
// this is a built-in function
|
||||
|
||||
return new Symbol("SUBR-" + arg.toString());
|
||||
}
|
||||
|
||||
throw new RuntimeException("SYMBOL-FUNCTION: undefined function " +
|
||||
arg);
|
||||
public UndefinedSymbolFunctionException(SExpression function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
throw new RuntimeException("SYMBOL-FUNCTION: " + arg +
|
||||
" is not a symbol");
|
||||
@Override
|
||||
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