Started writing tests for the builtin functions
This commit is contained in:
		
							parent
							
								
									715de2f220
								
							
						
					
					
						commit
						9bea0e6533
					
				@ -3,65 +3,46 @@ package function.builtin;
 | 
			
		||||
import function.*;
 | 
			
		||||
import sexpression.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * <code>APPLY</code> represents the APPLY function in Lisp.
 | 
			
		||||
 */
 | 
			
		||||
public class APPLY extends LispFunction {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Call APPLY with the specified argument list.
 | 
			
		||||
     *
 | 
			
		||||
     * @param argList
 | 
			
		||||
     *            the list of arguments to be sent to APPLY (MUST BE A PROPER LIST)
 | 
			
		||||
     * @return the result of evaluating APPLY on <code>argList</code>
 | 
			
		||||
     */
 | 
			
		||||
    private static final int NUMBER_OF_ARGUMENTS = 2;
 | 
			
		||||
    private ArgumentValidator argumentValidator;
 | 
			
		||||
 | 
			
		||||
    public static SExpression apply(Cons argList) {
 | 
			
		||||
        return new APPLY().call(argList);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The number of arguments that APPLY takes.
 | 
			
		||||
    private static final int NUM_ARGS = 2;
 | 
			
		||||
    public APPLY() {
 | 
			
		||||
        this.argumentValidator = new ArgumentValidator("APPLY");
 | 
			
		||||
        this.argumentValidator.setExactNumberOfArguments(NUMBER_OF_ARGUMENTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SExpression call(Cons argList) {
 | 
			
		||||
        // retrieve the number of arguments passed to APPLY
 | 
			
		||||
        int argListLength = LENGTH.getLength(argList);
 | 
			
		||||
        argumentValidator.validate(argList);
 | 
			
		||||
 | 
			
		||||
        // make sure we have received the proper number of arguments
 | 
			
		||||
        if (argListLength != NUM_ARGS) {
 | 
			
		||||
            Cons originalSExpr = new Cons(new Symbol("APPLY"), argList);
 | 
			
		||||
            String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to APPLY: "
 | 
			
		||||
                            + originalSExpr;
 | 
			
		||||
 | 
			
		||||
            throw new RuntimeException(errMsg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SExpression car = argList.getCar(); // function name
 | 
			
		||||
        Cons cdr = (Cons) argList.getCdr();
 | 
			
		||||
        SExpression cadr = cdr.getCar(); // argument list
 | 
			
		||||
        SExpression functionName = argList.getCar();
 | 
			
		||||
        SExpression argumentList = cdr.getCar();
 | 
			
		||||
 | 
			
		||||
        // make sure the second argument is a list
 | 
			
		||||
        if (cadr.listp()) {
 | 
			
		||||
            LispFunction function = EVAL.lookupFunction(car.toString());
 | 
			
		||||
        if (argumentList.listp()) {
 | 
			
		||||
            LispFunction function = EVAL.lookupFunction(functionName.toString());
 | 
			
		||||
 | 
			
		||||
            if (function == null) {
 | 
			
		||||
                // check if the car of the list is a lambda expression
 | 
			
		||||
                if (car.functionp()) {
 | 
			
		||||
                    function = ((LambdaExpression) car).getFunction();
 | 
			
		||||
                } else if (LAMBDA.isLambdaExpression(car)) {
 | 
			
		||||
                    Cons lexpr = (Cons) car;
 | 
			
		||||
                if (functionName.functionp()) {
 | 
			
		||||
                    function = ((LambdaExpression) functionName).getFunction();
 | 
			
		||||
                } else if (LAMBDA.isLambdaExpression(functionName)) {
 | 
			
		||||
                    Cons lexpr = (Cons) functionName;
 | 
			
		||||
 | 
			
		||||
                    function = LAMBDA.createFunction(lexpr);
 | 
			
		||||
                } else {
 | 
			
		||||
                    throw new RuntimeException("undefined function " + car);
 | 
			
		||||
                    throw new RuntimeException("undefined function " + functionName);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // apply the given function to the given argument list
 | 
			
		||||
            return function.call((Cons) cadr);
 | 
			
		||||
            return function.call((Cons) argumentList);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // the second argument is not a list
 | 
			
		||||
        throw new RuntimeException("APPLY: " + cadr + " is not a list");
 | 
			
		||||
        throw new RuntimeException("APPLY: " + argumentList + " is not a list");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,32 +1,23 @@
 | 
			
		||||
package function.builtin;
 | 
			
		||||
 | 
			
		||||
import function.LispFunction;
 | 
			
		||||
import function.*;
 | 
			
		||||
import sexpression.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * <code>ATOM</code> represents the ATOM function in Lisp.
 | 
			
		||||
 */
 | 
			
		||||
public class ATOM extends LispFunction {
 | 
			
		||||
 | 
			
		||||
    // The number of arguments that ATOM takes.
 | 
			
		||||
    private static final int NUM_ARGS = 1;
 | 
			
		||||
    private static final int NUMBER_OF_ARGUMENTS = 1;
 | 
			
		||||
    private ArgumentValidator argumentValidator;
 | 
			
		||||
 | 
			
		||||
    public SExpression call(Cons argList) {
 | 
			
		||||
        // retrieve the number of arguments passed to ATOM
 | 
			
		||||
        int argListLength = LENGTH.getLength(argList);
 | 
			
		||||
    public ATOM() {
 | 
			
		||||
        this.argumentValidator = new ArgumentValidator("ATOM");
 | 
			
		||||
        this.argumentValidator.setExactNumberOfArguments(NUMBER_OF_ARGUMENTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        // make sure we have received the proper number of arguments
 | 
			
		||||
        if (argListLength != NUM_ARGS) {
 | 
			
		||||
            Cons originalSExpr = new Cons(new Symbol("ATOM"), argList);
 | 
			
		||||
            String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to ATOM: "
 | 
			
		||||
                            + originalSExpr;
 | 
			
		||||
    public SExpression call(Cons argumentList) {
 | 
			
		||||
        argumentValidator.validate(argumentList);
 | 
			
		||||
        SExpression argument = argumentList.getCar();
 | 
			
		||||
 | 
			
		||||
            throw new RuntimeException(errMsg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SExpression arg = argList.getCar();
 | 
			
		||||
 | 
			
		||||
        return (arg.atomp() ? Symbol.T : Nil.getUniqueInstance());
 | 
			
		||||
        return argument.atomp() ? Symbol.T : Nil.getUniqueInstance();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
package function;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static testutil.TestUtilities.*;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
@ -35,7 +36,7 @@ public class UserDefinedFunctionTester {
 | 
			
		||||
                                 new Cons(Nil.getUniqueInstance(),
 | 
			
		||||
                                          new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())));
 | 
			
		||||
 | 
			
		||||
        assertEquals(expected.toString(), function.getLambdaExpression().toString());
 | 
			
		||||
        assertSExpressionsMatch(expected, function.getLambdaExpression());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -44,7 +45,7 @@ public class UserDefinedFunctionTester {
 | 
			
		||||
        SExpression argument = new LispNumber(23);
 | 
			
		||||
        Cons argumentList = new Cons(argument, Nil.getUniqueInstance());
 | 
			
		||||
 | 
			
		||||
        assertEquals(argument.toString(), function.call(argumentList).toString());
 | 
			
		||||
        assertSExpressionsMatch(argument, function.call(argumentList));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = TooManyArgumentsException.class)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								test/function/builtin/APPLYTester.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								test/function/builtin/APPLYTester.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
package function.builtin;
 | 
			
		||||
 | 
			
		||||
import static testutil.TestUtilities.*;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import function.ArgumentValidator.*;
 | 
			
		||||
import sexpression.Cons;
 | 
			
		||||
 | 
			
		||||
public class APPLYTester {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testApply() {
 | 
			
		||||
        String input = "(apply '+ '(1 2 3))";
 | 
			
		||||
 | 
			
		||||
        assertSExpressionsMatch(evaluateString(input), parseString("6"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testApplyWithLambdaExpression() {
 | 
			
		||||
        String input = "(apply (lambda (x) (+ x 1)) '(25))";
 | 
			
		||||
 | 
			
		||||
        assertSExpressionsMatch(evaluateString(input), parseString("26"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testApplyWithQuotedLambdaExpression() {
 | 
			
		||||
        String input = "(apply '(lambda (x) (+ x 1)) '(25))";
 | 
			
		||||
 | 
			
		||||
        assertSExpressionsMatch(evaluateString(input), parseString("26"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testStaticApplyCall() {
 | 
			
		||||
        String argumentList = "(+ (25 10))";
 | 
			
		||||
        Cons parsedArgumentList = (Cons) parseString(argumentList);
 | 
			
		||||
 | 
			
		||||
        assertSExpressionsMatch(APPLY.apply(parsedArgumentList), parseString("35"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = RuntimeException.class)
 | 
			
		||||
    public void testApplyWithUndefinedFunction() {
 | 
			
		||||
        evaluateString("(apply 'f '(1 2 3))");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = RuntimeException.class)
 | 
			
		||||
    public void testApplyWithNonListSecondArgument() {
 | 
			
		||||
        evaluateString("(apply '+ '2)");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = TooManyArgumentsException.class)
 | 
			
		||||
    public void testApplyWithTooManyArguments() {
 | 
			
		||||
        evaluateString("(apply '1 '2 '3)");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = TooFewArgumentsException.class)
 | 
			
		||||
    public void testApplyWithTooFewArguments() {
 | 
			
		||||
        evaluateString("(apply '1)");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								test/function/builtin/ATOMTester.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test/function/builtin/ATOMTester.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
package function.builtin;
 | 
			
		||||
 | 
			
		||||
import static testutil.TestUtilities.*;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import function.ArgumentValidator.*;
 | 
			
		||||
 | 
			
		||||
public class ATOMTester {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAtom_ReturnsTrue() {
 | 
			
		||||
        String input = "(atom 'a)";
 | 
			
		||||
 | 
			
		||||
        assertSExpressionsMatch(evaluateString(input), parseString("T"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAtom_ReturnsFalse() {
 | 
			
		||||
        String input = "(atom '(1 2 3))";
 | 
			
		||||
 | 
			
		||||
        assertSExpressionsMatch(evaluateString(input), parseString("()"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = TooManyArgumentsException.class)
 | 
			
		||||
    public void testApplyWithTooManyArguments() {
 | 
			
		||||
        evaluateString("(atom '1 '2)");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test(expected = TooFewArgumentsException.class)
 | 
			
		||||
    public void testApplyWithTooFewArguments() {
 | 
			
		||||
        evaluateString("(atom)");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
package parser;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.*;
 | 
			
		||||
import static parser.SExpressionTypeAssertions.*;
 | 
			
		||||
import static testutil.SExpressionTypeAssertions.*;
 | 
			
		||||
import static testutil.TestUtilities.createIOExceptionThrowingInputStream;
 | 
			
		||||
import static testutil.TestUtilities.createInputStreamFromString;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
package parser;
 | 
			
		||||
package testutil;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.*;
 | 
			
		||||
 | 
			
		||||
import sexpression.Nil;
 | 
			
		||||
import sexpression.SExpression;
 | 
			
		||||
import sexpression.*;
 | 
			
		||||
 | 
			
		||||
public final class SExpressionTypeAssertions {
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,19 @@
 | 
			
		||||
package testutil;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
import function.builtin.EVAL;
 | 
			
		||||
import parser.LispParser;
 | 
			
		||||
import sexpression.SExpression;
 | 
			
		||||
 | 
			
		||||
public final class TestUtilities {
 | 
			
		||||
 | 
			
		||||
    public static InputStream createInputStreamFromString(String string) {
 | 
			
		||||
        return new ByteArrayInputStream(string.getBytes());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public static InputStream createIOExceptionThrowingInputStream() {
 | 
			
		||||
        return new InputStream() {
 | 
			
		||||
 | 
			
		||||
@ -17,4 +23,18 @@ public final class TestUtilities {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static SExpression evaluateString(String input) {
 | 
			
		||||
        return EVAL.eval(parseString(input));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static SExpression parseString(String input) {
 | 
			
		||||
        InputStream stringInputStream = TestUtilities.createInputStreamFromString(input);
 | 
			
		||||
 | 
			
		||||
        return new LispParser(stringInputStream, "testFile").getNextSExpression();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void assertSExpressionsMatch(SExpression one, SExpression two) {
 | 
			
		||||
        assertEquals(one.toString(), two.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user