From c4531b25e2f707e923d7fd5485d306d469a88954 Mon Sep 17 00:00:00 2001 From: Mike Cifelli Date: Tue, 20 Dec 2016 12:03:37 -0500 Subject: [PATCH] Added unit tests and did some refactoring --- src/function/UserDefinedFunction.java | 60 ++++++------------ src/function/builtin/SYMBOL_FUNCTION.java | 2 +- test/function/LispFunctionTester.java | 24 +++++++ test/function/UserDefinedFunctionTester.java | 66 ++++++++++++++++++++ 4 files changed, 109 insertions(+), 43 deletions(-) create mode 100644 test/function/LispFunctionTester.java create mode 100644 test/function/UserDefinedFunctionTester.java diff --git a/src/function/UserDefinedFunction.java b/src/function/UserDefinedFunction.java index b7fd6bc..fd7e9ee 100644 --- a/src/function/UserDefinedFunction.java +++ b/src/function/UserDefinedFunction.java @@ -8,65 +8,47 @@ import table.SymbolTable; public class UserDefinedFunction extends LispFunction { - // the number of arguments that this user-defined function takes. - private final int NUM_ARGS; - + private ArgumentValidator argumentValidator; private String name; private Cons body; - private Cons lexpr; + private Cons lambdaExpression; private SymbolTable environment; - private ArrayList parameters; + private ArrayList formalParameters; /** - * Create a new user-defined function with the specified name, lambda list - * and body. + * Create a new user-defined function with the specified name, lambda list and body. * * @param name - * the name of this user-defined function + * the name of this user-defined function * @param lambdaList - * a list of the formal parameters of this user-defined function (MUST BE - * A PROPER LIST) + * a list of the formal parameters of this user-defined function (MUST BE A PROPER + * LIST) * @param body - * the body of this user-defined function (MUST BE A PROPER LIST) + * the body of this user-defined function (MUST BE A PROPER LIST) */ public UserDefinedFunction(String name, Cons lambdaList, Cons body) { this.name = name; this.body = body; - this.lexpr = new Cons(new Symbol(name), new Cons(lambdaList, body)); + this.lambdaExpression = new Cons(new Symbol(name), new Cons(lambdaList, body)); this.environment = SETF.getEnvironment(); - this.parameters = new ArrayList(); + this.formalParameters = new ArrayList(); - // retrieve the names of all the formal parameters of this function - while (lambdaList.consp()) { - this.parameters.add(lambdaList.getCar().toString()); + for (; lambdaList.consp(); lambdaList = (Cons) lambdaList.getCdr()) + this.formalParameters.add(lambdaList.getCar().toString()); - lambdaList = (Cons) lambdaList.getCdr(); - } - - this.NUM_ARGS = this.parameters.size(); + this.argumentValidator = new ArgumentValidator(this.name); + this.argumentValidator.setExactNumberOfArguments(this.formalParameters.size()); } public SExpression call(Cons argList) { - // retrieve the number of arguments passed to this function - int argListLength = LENGTH.getLength(argList); - - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol(name), argList); - String errMsg = "too " + - ((argListLength > NUM_ARGS) ? "many" : "few") + - " arguments given to " + name + ": " + - originalSExpr; - - throw new RuntimeException(errMsg); - } + argumentValidator.validate(argList); // push a new symbol table onto this function's environment (for its // parameters) environment = new SymbolTable(environment); // bind the values of the arguments to the formal parameter names - for (String param : parameters) { + for (String param : formalParameters) { SExpression currentArg = argList.getCar(); environment.put(param, currentArg); @@ -102,14 +84,8 @@ public class UserDefinedFunction extends LispFunction { return retval; } - /** - * Return the lambda expression that represents this user-defined function. - * - * @return - * the lambda expression that represents this user-defined function - */ - public Cons getLexpr() { - return lexpr; + public Cons getLambdaExpression() { + return lambdaExpression; } } diff --git a/src/function/builtin/SYMBOL_FUNCTION.java b/src/function/builtin/SYMBOL_FUNCTION.java index 5cd4762..8d7dfb1 100644 --- a/src/function/builtin/SYMBOL_FUNCTION.java +++ b/src/function/builtin/SYMBOL_FUNCTION.java @@ -41,7 +41,7 @@ public class SYMBOL_FUNCTION extends LispFunction { UserDefinedFunction udFunction = (UserDefinedFunction) function; - return udFunction.getLexpr(); + return udFunction.getLambdaExpression(); } // this is a built-in function diff --git a/test/function/LispFunctionTester.java b/test/function/LispFunctionTester.java new file mode 100644 index 0000000..f4541e7 --- /dev/null +++ b/test/function/LispFunctionTester.java @@ -0,0 +1,24 @@ +package function; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import sexpression.*; + +public class LispFunctionTester { + + @Test + public void testEvaluateArguments() { + LispFunction lispFunction = new LispFunction() { + + @Override + public SExpression call(Cons argList) { + return null; + } + }; + + assertTrue(lispFunction.evaluateArguments()); + } + +} diff --git a/test/function/UserDefinedFunctionTester.java b/test/function/UserDefinedFunctionTester.java new file mode 100644 index 0000000..ae8e69d --- /dev/null +++ b/test/function/UserDefinedFunctionTester.java @@ -0,0 +1,66 @@ +package function; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import function.ArgumentValidator.*; +import sexpression.*; + +public class UserDefinedFunctionTester { + + private static final String FUNCTION_NAME = "TEST"; + + private UserDefinedFunction createNoArgumentFunctionThatReturnsNil() { + return new UserDefinedFunction(FUNCTION_NAME, Nil.getUniqueInstance(), + new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())); + } + + private UserDefinedFunction createOneArgumentFunctionThatReturnsArgument() { + return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), Nil.getUniqueInstance()), + new Cons(new Symbol("X"), Nil.getUniqueInstance())); + } + + @Test + public void testNilFunctionCall() { + UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil(); + + assertEquals(Nil.getUniqueInstance(), function.call(Nil.getUniqueInstance())); + } + + @Test + public void testNilFunctionToString() { + UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil(); + Cons expected = new Cons(new Symbol(FUNCTION_NAME), + new Cons(Nil.getUniqueInstance(), + new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()))); + + assertEquals(expected.toString(), function.getLambdaExpression().toString()); + } + + @Test + public void oneArgumentFunction_ReturnsCorrectValue() { + UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); + SExpression argument = new LispNumber(23); + Cons argumentList = new Cons(argument, Nil.getUniqueInstance()); + + assertEquals(argument.toString(), function.call(argumentList).toString()); + } + + @Test(expected = TooManyArgumentsException.class) + public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() { + UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); + SExpression argument = new LispNumber(23); + Cons argumentList = new Cons(argument, new Cons(argument, Nil.getUniqueInstance())); + + function.call(argumentList); + } + + @Test(expected = TooFewArgumentsException.class) + public void oneArgumentFunction_ThrowsExceptionWithTooFewArguments() { + UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); + + function.call(Nil.getUniqueInstance()); + } + +}