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 {
 | 
					public class UserDefinedFunction extends LispFunction {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // the number of arguments that this user-defined function takes.
 | 
					    private ArgumentValidator argumentValidator;
 | 
				
			||||||
    private final int NUM_ARGS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private String name;
 | 
					    private String name;
 | 
				
			||||||
    private Cons body;
 | 
					    private Cons body;
 | 
				
			||||||
    private Cons lexpr;
 | 
					    private Cons lambdaExpression;
 | 
				
			||||||
    private SymbolTable environment;
 | 
					    private SymbolTable environment;
 | 
				
			||||||
    private ArrayList<String> parameters;
 | 
					    private ArrayList<String> formalParameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new user-defined function with the specified name, lambda list
 | 
					     * Create a new user-defined function with the specified name, lambda list and body.
 | 
				
			||||||
     * and body.
 | 
					 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param name
 | 
					     * @param name
 | 
				
			||||||
     *  the name of this user-defined function
 | 
					     *            the name of this user-defined function
 | 
				
			||||||
     * @param lambdaList
 | 
					     * @param lambdaList
 | 
				
			||||||
     *  a list of the formal parameters of this user-defined function (MUST BE
 | 
					     *            a list of the formal parameters of this user-defined function (MUST BE A PROPER
 | 
				
			||||||
     *  A PROPER LIST)
 | 
					     *            LIST)
 | 
				
			||||||
     * @param body
 | 
					     * @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) {
 | 
					    public UserDefinedFunction(String name, Cons lambdaList, Cons body) {
 | 
				
			||||||
        this.name = name;
 | 
					        this.name = name;
 | 
				
			||||||
        this.body = body;
 | 
					        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.environment = SETF.getEnvironment();
 | 
				
			||||||
        this.parameters = new ArrayList<String>();
 | 
					        this.formalParameters = new ArrayList<String>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // retrieve the names of all the formal parameters of this function
 | 
					        for (; lambdaList.consp(); lambdaList = (Cons) lambdaList.getCdr())
 | 
				
			||||||
        while (lambdaList.consp()) {
 | 
					            this.formalParameters.add(lambdaList.getCar().toString());
 | 
				
			||||||
            this.parameters.add(lambdaList.getCar().toString());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lambdaList = (Cons) lambdaList.getCdr();
 | 
					        this.argumentValidator = new ArgumentValidator(this.name);
 | 
				
			||||||
        }
 | 
					        this.argumentValidator.setExactNumberOfArguments(this.formalParameters.size());
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.NUM_ARGS = this.parameters.size();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SExpression call(Cons argList) {
 | 
					    public SExpression call(Cons argList) {
 | 
				
			||||||
        // retrieve the number of arguments passed to this function
 | 
					        argumentValidator.validate(argList);
 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // push a new symbol table onto this function's environment (for its
 | 
					        // push a new symbol table onto this function's environment (for its
 | 
				
			||||||
        // parameters)
 | 
					        // parameters)
 | 
				
			||||||
        environment = new SymbolTable(environment);
 | 
					        environment = new SymbolTable(environment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // bind the values of the arguments to the formal parameter names
 | 
					        // bind the values of the arguments to the formal parameter names
 | 
				
			||||||
        for (String param : parameters) {
 | 
					        for (String param : formalParameters) {
 | 
				
			||||||
            SExpression currentArg = argList.getCar();
 | 
					            SExpression currentArg = argList.getCar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            environment.put(param, currentArg);
 | 
					            environment.put(param, currentArg);
 | 
				
			||||||
@ -102,14 +84,8 @@ public class UserDefinedFunction extends LispFunction {
 | 
				
			|||||||
        return retval;
 | 
					        return retval;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public Cons getLambdaExpression() {
 | 
				
			||||||
     * Return the lambda expression that represents this user-defined function.
 | 
					        return lambdaExpression;
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return
 | 
					 | 
				
			||||||
     *  the lambda expression that represents this user-defined function
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public Cons getLexpr() {
 | 
					 | 
				
			||||||
        return lexpr;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ public class SYMBOL_FUNCTION extends LispFunction {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    UserDefinedFunction udFunction = (UserDefinedFunction) function;
 | 
					                    UserDefinedFunction udFunction = (UserDefinedFunction) function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return udFunction.getLexpr();
 | 
					                    return udFunction.getLambdaExpression();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // this is a built-in function
 | 
					                // this is a built-in function
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								test/function/LispFunctionTester.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								test/function/LispFunctionTester.java
									
									
									
									
									
										Normal file
									
								
							@ -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());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										66
									
								
								test/function/UserDefinedFunctionTester.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								test/function/UserDefinedFunctionTester.java
									
									
									
									
									
										Normal file
									
								
							@ -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
	
	Block a user