Added unit tests and did some refactoring
This commit is contained in:
parent
621ab9f2cb
commit
c4531b25e2
|
@ -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<String> parameters;
|
||||
private ArrayList<String> 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
|
||||
* @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)
|
||||
*/
|
||||
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<String>();
|
||||
this.formalParameters = new ArrayList<String>();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue