diff --git a/src/function/builtin/ATOM.java b/src/function/builtin/ATOM.java index 1cb8775..4be2e9f 100644 --- a/src/function/builtin/ATOM.java +++ b/src/function/builtin/ATOM.java @@ -16,7 +16,7 @@ public class ATOM extends LispFunction { argumentValidator.validate(argumentList); SExpression argument = argumentList.getCar(); - return argument.atomp() ? Symbol.T : Nil.getUniqueInstance(); + return argument.atomp() ? Symbol.T : Nil.getInstance(); } } diff --git a/src/function/builtin/COND.java b/src/function/builtin/COND.java index 3171081..05b1fe4 100644 --- a/src/function/builtin/COND.java +++ b/src/function/builtin/COND.java @@ -21,7 +21,7 @@ public class COND extends LispFunction { private SExpression callTailRecursive(Cons argumentList) { if (argumentList.nullp()) - return Nil.getUniqueInstance(); + return Nil.getInstance(); Cons clause = (Cons) argumentList.getCar(); Cons remainingClauses = (Cons) argumentList.getCdr(); @@ -34,7 +34,7 @@ public class COND extends LispFunction { } private boolean isTestSuccessful(SExpression test) { - return test != Nil.getUniqueInstance(); + return test != Nil.getInstance(); } private SExpression evaluateResult(Cons clause, SExpression test) { diff --git a/src/function/builtin/DIVIDE.java b/src/function/builtin/DIVIDE.java index c8bd044..f9efa8c 100644 --- a/src/function/builtin/DIVIDE.java +++ b/src/function/builtin/DIVIDE.java @@ -2,54 +2,50 @@ package function.builtin; import java.math.BigInteger; -import function.LispFunction; +import function.*; import sexpression.*; -/** - * DIVIDE represents the '/' function in Lisp. - */ public class DIVIDE extends LispFunction { - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("/"), argList); + private ArgumentValidator argumentValidator; - throw new RuntimeException("too few arguments given to /: " + originalSExpr); - } + public DIVIDE() { + this.argumentValidator = new ArgumentValidator("/"); + this.argumentValidator.setMinimumNumberOfArguments(1); + this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); + } - SExpression argFirst = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); - // make sure that the first argument is a number - if (argFirst.numberp()) { - LispNumber num1 = (LispNumber) argFirst; + return callTailRecursive(argumentList); + } - if (argRest.nullp()) { - // there is only one argument, so return the multiplicative - // inverse of the number - return new LispNumber(BigInteger.ONE.divide(num1.getValue())); - } + private SExpression callTailRecursive(Cons argumentList) { + Cons remainingArguments = (Cons) argumentList.getCdr(); + SExpression firstArgument = argumentList.getCar(); + LispNumber number1 = (LispNumber) firstArgument; - SExpression argSecond = argRest.getCar(); + if (remainingArguments.nullp()) + return getReciprocal(number1); - // make sure that the next argument is a number as well - if (argSecond.numberp()) { - LispNumber num2 = (LispNumber) argSecond; - LispNumber quotient = new LispNumber(num1.getValue().divide(num2.getValue())); - SExpression argCddr = argRest.getCdr(); + SExpression secondArgument = remainingArguments.getCar(); + LispNumber number2 = (LispNumber) secondArgument; + LispNumber quotient = divide(number1, number2); + SExpression remainingNumbers = remainingArguments.getCdr(); - if (argCddr.consp()) { - return call(new Cons(quotient, argCddr)); - } + if (remainingNumbers.nullp()) + return quotient; - return quotient; - } + return callTailRecursive(new Cons(quotient, remainingNumbers)); + } - throw new RuntimeException("/: " + argSecond + " is not a number"); - } + private LispNumber getReciprocal(LispNumber number1) { + return new LispNumber(BigInteger.ONE.divide(number1.getValue())); + } - throw new RuntimeException("/: " + argFirst + " is not a number"); + private LispNumber divide(LispNumber number1, LispNumber number2) { + return new LispNumber(number1.getValue().divide(number2.getValue())); } } diff --git a/src/function/builtin/EQ.java b/src/function/builtin/EQ.java index 9d98d3d..6857537 100644 --- a/src/function/builtin/EQ.java +++ b/src/function/builtin/EQ.java @@ -1,38 +1,44 @@ package function.builtin; -import function.LispFunction; +import function.*; import sexpression.*; -/** - * EQ represents the EQ function in Lisp. - */ public class EQ extends LispFunction { - // The number of arguments that EQ takes. - private static final int NUM_ARGS = 2; + private ArgumentValidator argumentValidator; - public SExpression call(Cons argList) { - // retrieve the number of arguments passed to EQ - int argListLength = LENGTH.getLength(argList); + public EQ() { + this.argumentValidator = new ArgumentValidator("EQ"); + this.argumentValidator.setExactNumberOfArguments(2); + } - // make sure we have received the proper number of arguments - if (argListLength != NUM_ARGS) { - Cons originalSExpr = new Cons(new Symbol("EQ"), argList); - String errMsg = "too " + ((argListLength > NUM_ARGS) ? "many" : "few") + " arguments given to EQ: " - + originalSExpr; + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); - throw new RuntimeException(errMsg); - } + Cons cdr = (Cons) argumentList.getCdr(); + SExpression firstArgument = argumentList.getCar(); + SExpression secondArgument = cdr.getCar(); - SExpression argOne = argList.getCar(); // first argument - Cons cdr = (Cons) argList.getCdr(); - SExpression argTwo = cdr.getCar(); // second argumnet + return eq(firstArgument, secondArgument); + } - if (argOne.atomp() && argTwo.atomp()) { - return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getUniqueInstance()); - } + private SExpression eq(SExpression firstArgument, SExpression secondArgument) { + if (isAtomPair(firstArgument, secondArgument)) + return atomEq(firstArgument, secondArgument); - return ((argOne == argTwo) ? Symbol.T : Nil.getUniqueInstance()); + return listEq(firstArgument, secondArgument); + } + + private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) { + return firstArgument.atomp() && secondArgument.atomp(); + } + + private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) { + return (firstArgument.toString().equals(secondArgument.toString())) ? Symbol.T : Nil.getInstance(); + } + + private SExpression listEq(SExpression firstArgument, SExpression secondArgument) { + return (firstArgument == secondArgument) ? Symbol.T : Nil.getInstance(); } } diff --git a/src/function/builtin/EQUAL.java b/src/function/builtin/EQUAL.java index 2a9ec1b..72ad6a4 100644 --- a/src/function/builtin/EQUAL.java +++ b/src/function/builtin/EQUAL.java @@ -39,10 +39,10 @@ public class EQUAL extends LispFunction { SExpression carEqual = call(new Cons(listOneCar, LIST.makeList(listTwoCar))); SExpression cdrEqual = call(new Cons(listOneCdr, LIST.makeList(listTwoCdr))); - return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) ? Symbol.T : Nil.getUniqueInstance()); + return (((carEqual == Symbol.T) && (cdrEqual == Symbol.T)) ? Symbol.T : Nil.getInstance()); } - return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getUniqueInstance()); + return ((argOne.toString().equals(argTwo.toString())) ? Symbol.T : Nil.getInstance()); } } diff --git a/src/function/builtin/EQUALSP.java b/src/function/builtin/EQUALSP.java index deff065..5882e87 100644 --- a/src/function/builtin/EQUALSP.java +++ b/src/function/builtin/EQUALSP.java @@ -1,49 +1,43 @@ package function.builtin; -import function.LispFunction; +import function.*; import sexpression.*; -/** - * EQUALSP represents the '=' function in Lisp. - */ public class EQUALSP extends LispFunction { - public SExpression call(Cons argList) { - // make sure we have received at least one argument - if (argList.nullp()) { - Cons originalSExpr = new Cons(new Symbol("="), argList); + private ArgumentValidator argumentValidator; - throw new RuntimeException("too few arguments given to =: " + originalSExpr); - } + public EQUALSP() { + this.argumentValidator = new ArgumentValidator("="); + this.argumentValidator.setMinimumNumberOfArguments(1); + this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); + } - SExpression firstArg = argList.getCar(); - Cons argRest = (Cons) argList.getCdr(); + public SExpression call(Cons argumentList) { + argumentValidator.validate(argumentList); - // make sure that the first argument is a number - if (firstArg.numberp()) { - LispNumber num1 = (LispNumber) firstArg; + return callTailRecursive(argumentList); + } - if (argRest.nullp()) { - return Symbol.T; - } + private SExpression callTailRecursive(Cons argumentList) { + Cons remainingArguments = (Cons) argumentList.getCdr(); - SExpression secondArg = argRest.getCar(); + if (remainingArguments.nullp()) + return Symbol.T; - // make sure that the second argument is a number as well - if (secondArg.numberp()) { - LispNumber num2 = (LispNumber) secondArg; + SExpression firstArgument = argumentList.getCar(); + LispNumber number1 = (LispNumber) firstArgument; + SExpression secondArgument = remainingArguments.getCar(); + LispNumber number2 = (LispNumber) secondArgument; - if (num1.getValue().equals(num2.getValue())) { - return call(argRest); - } + if (!isEqual(number1, number2)) + return Nil.getInstance(); - return Nil.getUniqueInstance(); - } + return callTailRecursive(remainingArguments); + } - throw new RuntimeException("=: " + secondArg + " is not a number"); - } - - throw new RuntimeException("=: " + firstArg + " is not a number"); + private boolean isEqual(LispNumber number1, LispNumber number2) { + return number1.getValue().equals(number2.getValue()); } } diff --git a/src/function/builtin/EVAL.java b/src/function/builtin/EVAL.java index d965588..19feb34 100644 --- a/src/function/builtin/EVAL.java +++ b/src/function/builtin/EVAL.java @@ -73,7 +73,7 @@ public class EVAL extends LispFunction { public static SExpression lookupSymbol(String symbolName) { if (symbolName.equals("NIL")) { - return Nil.getUniqueInstance(); + return Nil.getInstance(); } else if (symbolName.equals("T")) { return Symbol.T; } else if (symbolName.startsWith(":")) { @@ -173,7 +173,7 @@ public class EVAL extends LispFunction { private Cons evaluateArgList(Cons arguments) { if (arguments.nullp()) { - return Nil.getUniqueInstance(); + return Nil.getInstance(); } SExpression car = eval(arguments.getCar()); @@ -185,7 +185,7 @@ public class EVAL extends LispFunction { // remove any parameters found after a dot (put here in case the check // for a dotted parameter list is not done prior to this call) - return new Cons(car, Nil.getUniqueInstance()); + return new Cons(car, Nil.getInstance()); } } diff --git a/src/function/builtin/GREATERP.java b/src/function/builtin/GREATERP.java index fed1bbf..a4ed18a 100644 --- a/src/function/builtin/GREATERP.java +++ b/src/function/builtin/GREATERP.java @@ -37,7 +37,7 @@ public class GREATERP extends LispFunction { return call(argRest); } - return Nil.getUniqueInstance(); + return Nil.getInstance(); } throw new RuntimeException(">: " + secondArg + " is not a number"); diff --git a/src/function/builtin/LESSP.java b/src/function/builtin/LESSP.java index 9275327..82c3ade 100644 --- a/src/function/builtin/LESSP.java +++ b/src/function/builtin/LESSP.java @@ -37,7 +37,7 @@ public class LESSP extends LispFunction { return call(argRest); } - return Nil.getUniqueInstance(); + return Nil.getInstance(); } throw new RuntimeException("<: " + secondArg + " is not a number"); diff --git a/src/function/builtin/LET.java b/src/function/builtin/LET.java index 80698cb..2d16de3 100644 --- a/src/function/builtin/LET.java +++ b/src/function/builtin/LET.java @@ -25,7 +25,7 @@ public class LET extends LispFunction { addVariablesToTable(environment, car); SETF.setEnvironment(environment); - SExpression retval = Nil.getUniqueInstance(); + SExpression retval = Nil.getInstance(); // evaluate all S-expression in the body while (cdr.consp()) { diff --git a/src/function/builtin/LIST.java b/src/function/builtin/LIST.java index 0bcf90e..0dc83cc 100644 --- a/src/function/builtin/LIST.java +++ b/src/function/builtin/LIST.java @@ -17,13 +17,13 @@ public class LIST extends LispFunction { * a list with sexpr as the car and NIL as the cdr. */ public static Cons makeList(SExpression sexpr) { - return new Cons(sexpr, Nil.getUniqueInstance()); + return new Cons(sexpr, Nil.getInstance()); } public Cons call(Cons argList) { if (argList.nullp()) { // return NIL if there were no arguments passed to LIST - return Nil.getUniqueInstance(); + return Nil.getInstance(); } SExpression argCar = argList.getCar(); diff --git a/src/function/builtin/LISTP.java b/src/function/builtin/LISTP.java index 1db2101..4519ba1 100644 --- a/src/function/builtin/LISTP.java +++ b/src/function/builtin/LISTP.java @@ -26,7 +26,7 @@ public class LISTP extends LispFunction { SExpression arg = argList.getCar(); - return (arg.listp() ? Symbol.T : Nil.getUniqueInstance()); + return (arg.listp() ? Symbol.T : Nil.getInstance()); } } diff --git a/src/function/builtin/LOAD.java b/src/function/builtin/LOAD.java index b02ebb7..c03ee1a 100644 --- a/src/function/builtin/LOAD.java +++ b/src/function/builtin/LOAD.java @@ -58,7 +58,7 @@ public class LOAD extends LispFunction { } catch (FileNotFoundException e) { System.out.println("LOAD: could not open " + fileName); - return Nil.getUniqueInstance(); + return Nil.getInstance(); } // attempt to evaluate all the S-expressions contained in the file @@ -70,7 +70,7 @@ public class LOAD extends LispFunction { } catch (RuntimeException e) { System.out.println("LOAD: " + e.getMessage()); - return Nil.getUniqueInstance(); + return Nil.getInstance(); } } diff --git a/src/function/builtin/NULL.java b/src/function/builtin/NULL.java index 19607e7..50dc455 100644 --- a/src/function/builtin/NULL.java +++ b/src/function/builtin/NULL.java @@ -26,7 +26,7 @@ public class NULL extends LispFunction { SExpression arg = argList.getCar(); - return (arg.nullp() ? Symbol.T : Nil.getUniqueInstance()); + return (arg.nullp() ? Symbol.T : Nil.getInstance()); } } diff --git a/src/sexpression/Nil.java b/src/sexpression/Nil.java index 49d9388..6b1977a 100644 --- a/src/sexpression/Nil.java +++ b/src/sexpression/Nil.java @@ -5,7 +5,7 @@ public class Nil extends Cons { private static Nil uniqueInstance = new Nil(); - public static Nil getUniqueInstance() { + public static Nil getInstance() { return uniqueInstance; } @@ -33,14 +33,12 @@ public class Nil extends Cons { } /** - * Set the car of this CONS cell to the specified value. This method does nothing (the car of - * NIL can not be changed). + * The car of NIL can not be changed. */ public void setCar(SExpression newCar) {} /** - * Set the cdr of this CONS cell to the specified value. This method does nothing (the cdr of - * NIL can not be changed). + * The cdr of NIL can not be changed. */ public void setCdr(SExpression newCdr) {} diff --git a/src/token/QuoteMark.java b/src/token/QuoteMark.java index 64ee3f4..660bd5d 100644 --- a/src/token/QuoteMark.java +++ b/src/token/QuoteMark.java @@ -16,7 +16,7 @@ public class QuoteMark extends Token { Token nextToken = getNextToken.get(); SExpression argument = nextToken.parseSExpression(getNextToken); - return new Cons(Symbol.createQuote(), new Cons(argument, Nil.getUniqueInstance())); + return new Cons(Symbol.createQuote(), new Cons(argument, Nil.getInstance())); } } diff --git a/src/token/RightParenthesis.java b/src/token/RightParenthesis.java index f94db7e..26ac921 100644 --- a/src/token/RightParenthesis.java +++ b/src/token/RightParenthesis.java @@ -19,7 +19,7 @@ public class RightParenthesis extends Token { @Override public SExpression parseSExpressionTail(Supplier getNextToken) { - return Nil.getUniqueInstance(); + return Nil.getInstance(); } public static class StartsWithRightParenthesisException extends LineColumnException { diff --git a/test/function/ArgumentValidatorTester.java b/test/function/ArgumentValidatorTester.java index c102956..97ae1d3 100644 --- a/test/function/ArgumentValidatorTester.java +++ b/test/function/ArgumentValidatorTester.java @@ -13,10 +13,10 @@ public class ArgumentValidatorTester { private ArgumentValidator validator; private Cons makeArgumentListOfSize(int size) { - Cons argumentList = Nil.getUniqueInstance(); + Cons argumentList = Nil.getInstance(); for (int i = 0; i < size; i++) - argumentList = new Cons(Nil.getUniqueInstance(), argumentList); + argumentList = new Cons(Nil.getInstance(), argumentList); return argumentList; } @@ -73,14 +73,14 @@ public class ArgumentValidatorTester { @Test public void tooManyArgumentsException_HasCorrectSeverity() { - TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getUniqueInstance()); + TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getInstance()); assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); } @Test public void tooManyArgumentsException_HasMessageText() { - TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getUniqueInstance()); + TooManyArgumentsException e = new TooManyArgumentsException("TEST", Nil.getInstance()); assertNotNull(e.getMessage()); assertTrue(e.getMessage().length() > 0); @@ -88,14 +88,14 @@ public class ArgumentValidatorTester { @Test public void tooFewArgumentsException_HasCorrectSeverity() { - TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getUniqueInstance()); + TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getInstance()); assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); } @Test public void tooFewArgumentsException_HasMessageText() { - TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getUniqueInstance()); + TooFewArgumentsException e = new TooFewArgumentsException("TEST", Nil.getInstance()); assertNotNull(e.getMessage()); assertTrue(e.getMessage().length() > 0); @@ -103,14 +103,14 @@ public class ArgumentValidatorTester { @Test public void BadArgumentTypeException_HasCorrectSeverity() { - BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getUniqueInstance(), SExpression.class); + BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getInstance(), SExpression.class); assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); } @Test public void BadArgumentTypeException_HasMessageText() { - BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getUniqueInstance(), SExpression.class); + BadArgumentTypeException e = new BadArgumentTypeException("TEST", Nil.getInstance(), SExpression.class); assertNotNull(e.getMessage()); assertTrue(e.getMessage().length() > 0); @@ -130,7 +130,7 @@ public class ArgumentValidatorTester { @Test public void correctFirstAndRestArgumentTypes_DoesNotThrowException() { - Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())); + Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance())); validator.setFirstArgumentExpectedType(Symbol.class); validator.setTrailingArgumentExpectedType(Cons.class); @@ -139,7 +139,7 @@ public class ArgumentValidatorTester { @Test(expected = BadArgumentTypeException.class) public void badFirstArgumentType_ThrowsException() { - Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())); + Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance())); validator.setFirstArgumentExpectedType(Cons.class); validator.setTrailingArgumentExpectedType(Cons.class); @@ -148,7 +148,7 @@ public class ArgumentValidatorTester { @Test(expected = BadArgumentTypeException.class) public void badTrailingArgumentType_ThrowsException() { - Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())); + Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance())); validator.setFirstArgumentExpectedType(Symbol.class); validator.setTrailingArgumentExpectedType(Symbol.class); @@ -157,7 +157,7 @@ public class ArgumentValidatorTester { @Test public void expectedTypeWithNoDisplayName_DoesNotCauseNPE() { - Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance())); + Cons argumentList = new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance())); SExpression withoutDisplayName = new SExpression() {}; validator.setEveryArgumentExpectedType(withoutDisplayName.getClass()); @@ -186,14 +186,14 @@ public class ArgumentValidatorTester { @Test public void DottedArgumentListException_HasCorrectSeverity() { - DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance()); + DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getInstance()); assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); } @Test public void dottedArgumentListException_HasMessageText() { - DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getUniqueInstance()); + DottedArgumentListException e = new DottedArgumentListException("TEST", Nil.getInstance()); assertNotNull(e.getMessage()); assertTrue(e.getMessage().length() > 0); @@ -202,19 +202,19 @@ public class ArgumentValidatorTester { @Test(expected = BadArgumentTypeException.class) public void doNotAcceptNil_ThrowsExceptionOnNilArgument() { validator.doNotAcceptNil(); - validator.validate(new Cons(Symbol.T, new Cons(Nil.getUniqueInstance(), Nil.getUniqueInstance()))); + validator.validate(new Cons(Symbol.T, new Cons(Nil.getInstance(), Nil.getInstance()))); } @Test public void doNotAcceptNil_AllowsEmptyArgumentList() { validator.doNotAcceptNil(); - validator.validate(Nil.getUniqueInstance()); + validator.validate(Nil.getInstance()); } @Test public void doNotAcceptNil_AllowsProperList() { validator.doNotAcceptNil(); - validator.validate(new Cons(Symbol.T, new Cons(Symbol.T, Nil.getUniqueInstance()))); + validator.validate(new Cons(Symbol.T, new Cons(Symbol.T, Nil.getInstance()))); } } diff --git a/test/function/UserDefinedFunctionTester.java b/test/function/UserDefinedFunctionTester.java index 7546b74..7ba85ea 100644 --- a/test/function/UserDefinedFunctionTester.java +++ b/test/function/UserDefinedFunctionTester.java @@ -13,28 +13,28 @@ 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())); + return new UserDefinedFunction(FUNCTION_NAME, Nil.getInstance(), + new Cons(Nil.getInstance(), Nil.getInstance())); } private UserDefinedFunction createOneArgumentFunctionThatReturnsArgument() { - return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), Nil.getUniqueInstance()), - new Cons(new Symbol("X"), Nil.getUniqueInstance())); + return new UserDefinedFunction(FUNCTION_NAME, new Cons(new Symbol("X"), Nil.getInstance()), + new Cons(new Symbol("X"), Nil.getInstance())); } @Test public void testNilFunctionCall() { UserDefinedFunction function = createNoArgumentFunctionThatReturnsNil(); - assertEquals(Nil.getUniqueInstance(), function.call(Nil.getUniqueInstance())); + assertEquals(Nil.getInstance(), function.call(Nil.getInstance())); } @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()))); + new Cons(Nil.getInstance(), + new Cons(Nil.getInstance(), Nil.getInstance()))); assertSExpressionsMatch(expected, function.getLambdaExpression()); } @@ -43,7 +43,7 @@ public class UserDefinedFunctionTester { public void oneArgumentFunction_ReturnsCorrectValue() { UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); SExpression argument = new LispNumber("23"); - Cons argumentList = new Cons(argument, Nil.getUniqueInstance()); + Cons argumentList = new Cons(argument, Nil.getInstance()); assertSExpressionsMatch(argument, function.call(argumentList)); } @@ -52,7 +52,7 @@ public class UserDefinedFunctionTester { public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() { UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); SExpression argument = new LispNumber("23"); - Cons argumentList = new Cons(argument, new Cons(argument, Nil.getUniqueInstance())); + Cons argumentList = new Cons(argument, new Cons(argument, Nil.getInstance())); function.call(argumentList); } @@ -61,7 +61,7 @@ public class UserDefinedFunctionTester { public void oneArgumentFunction_ThrowsExceptionWithTooFewArguments() { UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); - function.call(Nil.getUniqueInstance()); + function.call(Nil.getInstance()); } } diff --git a/test/function/builtin/DIVIDETester.java b/test/function/builtin/DIVIDETester.java new file mode 100644 index 0000000..634d573 --- /dev/null +++ b/test/function/builtin/DIVIDETester.java @@ -0,0 +1,63 @@ +package function.builtin; + +import static testutil.TestUtilities.*; + +import org.junit.Test; + +import function.ArgumentValidator.*; + +public class DIVIDETester { + + @Test + public void testDivideWithOne() { + String input = "(/ 1)"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test + public void testDivideWithTwo() { + String input = "(/ 2)"; + + assertSExpressionsMatch(evaluateString(input), parseString("0")); + } + + @Test + public void testDivideTwoNumbers() { + String input = "(/ 24 3)"; + + assertSExpressionsMatch(evaluateString(input), parseString("8")); + } + + @Test + public void testDivideSeveralNumbers() { + String input = "(/ 256 2 2 8)"; + + assertSExpressionsMatch(evaluateString(input), parseString("8")); + } + + @Test + public void testDivideTwoNumbersWithRemainder() { + String input = "(/ 9 2)"; + + assertSExpressionsMatch(evaluateString(input), parseString("4")); + } + + @Test + public void testDivideSeveralNumbersWithRemainder() { + String input = "(/ 19 2 5)"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test(expected = BadArgumentTypeException.class) + public void testDivideWithNonNumber() { + evaluateString("(/ 'x)"); + } + + @Test(expected = TooFewArgumentsException.class) + public void testDivideWithTooFewArguments() { + evaluateString("(/)"); + } + +} diff --git a/test/function/builtin/EQTester.java b/test/function/builtin/EQTester.java new file mode 100644 index 0000000..6af3b00 --- /dev/null +++ b/test/function/builtin/EQTester.java @@ -0,0 +1,67 @@ +package function.builtin; + +import static testutil.TestUtilities.*; + +import org.junit.Test; + +import function.ArgumentValidator.*; + +public class EQTester { + + @Test + public void testEqWithEqualAtoms() { + String input = "(eq 1 1)"; + + assertSExpressionsMatch(evaluateString(input), parseString("t")); + } + + @Test + public void testEqWithUnequalAtoms() { + String input = "(eq 1 2)"; + + assertSExpressionsMatch(evaluateString(input), parseString("nil")); + } + @Test + public void testEqWithAtomAndList() { + String input = "(eq 1 '(2))"; + + assertSExpressionsMatch(evaluateString(input), parseString("nil")); + } + + @Test + public void testEqWithSameList() { + String initializeL1 = "(setf l1 '(1 2 3))"; + String initializeL2 = "(setf l2 l1)"; + String input = "(eq l1 l2)"; + + evaluateString(initializeL1); + evaluateString(initializeL2); + + assertSExpressionsMatch(evaluateString(input), parseString("t")); + } + + @Test + public void testEqWithEqualLists() { + String input = "(eq '(1 2) '(1 2))"; + + assertSExpressionsMatch(evaluateString(input), parseString("nil")); + } + + @Test + public void testEqWithUnequalLists() { + String input = "(eq '(1 2) '(3 4))"; + + assertSExpressionsMatch(evaluateString(input), parseString("nil")); + } + + @Test(expected = TooManyArgumentsException.class) + public void testEqWithTooManyArguments() { + evaluateString("(eq 'one 'two 'three)"); + } + + @Test(expected = TooFewArgumentsException.class) + public void testEqWithTooFewArguments() { + evaluateString("(eq 'one)"); + } + +} diff --git a/test/function/builtin/EQUALSPTester.java b/test/function/builtin/EQUALSPTester.java new file mode 100644 index 0000000..cd19a3a --- /dev/null +++ b/test/function/builtin/EQUALSPTester.java @@ -0,0 +1,56 @@ +package function.builtin; + +import static testutil.TestUtilities.*; + +import org.junit.Test; + +import function.ArgumentValidator.*; + +public class EQUALSPTester { + + @Test + public void testEqualspWithOneNumber() { + String input = "(= 1)"; + + assertSExpressionsMatch(evaluateString(input), parseString("t")); + } + + @Test + public void testEqualspWithEqualNumbers() { + String input = "(= 1 1)"; + + assertSExpressionsMatch(evaluateString(input), parseString("t")); + } + + @Test + public void testEqualspWithNonEqualNumbers() { + String input = "(= 1 2)"; + + assertSExpressionsMatch(evaluateString(input), parseString("nil")); + } + + @Test + public void testEqualspWithManyEqualNumbers() { + String input = "(= 4 4 4 4 4 4 4 4 4 4)"; + + assertSExpressionsMatch(evaluateString(input), parseString("t")); + } + + @Test + public void testEqualspWithManyNonEqualNumbers() { + String input = "(= 4 4 4 4 5 4 4 4 4 4)"; + + assertSExpressionsMatch(evaluateString(input), parseString("nil")); + } + + @Test(expected = BadArgumentTypeException.class) + public void testEqualspWithNonNumbers() { + evaluateString("(= 'x 'x)"); + } + + @Test(expected = TooFewArgumentsException.class) + public void testEqualspWithTooFewArguments() { + evaluateString("(=)"); + } + +} diff --git a/test/function/builtin/EQUALTester.java b/test/function/builtin/EQUALTester.java new file mode 100644 index 0000000..13e21ce --- /dev/null +++ b/test/function/builtin/EQUALTester.java @@ -0,0 +1,47 @@ +package function.builtin; + +import static testutil.TestUtilities.*; + +import org.junit.Test; + +import function.ArgumentValidator.*; + +public class EQUALTester { + + @Test + public void testCarWithNil() { + String input = "(car nil)"; + + assertSExpressionsMatch(evaluateString(input), parseString("()")); + } + + @Test + public void testCarWithList() { + String input = "(car '(1 2 3))"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test + public void testNestedCarWithList() { + String input = "(car (car '((1 2) 3)))"; + + assertSExpressionsMatch(evaluateString(input), parseString("1")); + } + + @Test(expected = BadArgumentTypeException.class) + public void testCarWithNonList() { + evaluateString("(car 'x)"); + } + + @Test(expected = TooManyArgumentsException.class) + public void testCarWithTooManyArguments() { + evaluateString("(car '(1 2) '(1 2) \"oh\")"); + } + + @Test(expected = TooFewArgumentsException.class) + public void testCarWithTooFewArguments() { + evaluateString("(car)"); + } + +} diff --git a/test/sexpression/SExpressionTester.java b/test/sexpression/SExpressionTester.java index 014fa75..4e9a332 100644 --- a/test/sexpression/SExpressionTester.java +++ b/test/sexpression/SExpressionTester.java @@ -23,7 +23,7 @@ public class SExpressionTester { public void testNilToString() { String input = "NIL"; - assertSExpressionMatchesString(input, Nil.getUniqueInstance()); + assertSExpressionMatchesString(input, Nil.getInstance()); } @Test @@ -57,7 +57,7 @@ public class SExpressionTester { @Test public void testSimpleConsToString() { String expected = "(1)"; - Cons cons = new Cons(new LispNumber("1"), Nil.getUniqueInstance()); + Cons cons = new Cons(new LispNumber("1"), Nil.getInstance()); assertSExpressionMatchesString(expected, cons); } @@ -67,7 +67,7 @@ public class SExpressionTester { String expected = "(1 A \"string\")"; Cons list = new Cons(new LispNumber("1"), new Cons(new Symbol("a"), - new Cons(new LispString("\"string\""), Nil.getUniqueInstance()))); + new Cons(new LispString("\"string\""), Nil.getInstance()))); assertSExpressionMatchesString(expected, list); } @@ -83,7 +83,7 @@ public class SExpressionTester { @Test public void testLambdaExpressionToString() { String expected = "(LAMBDA)"; - LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getUniqueInstance()), null); + LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getInstance()), null); assertSExpressionMatchesString(expected, lambda); } @@ -91,7 +91,7 @@ public class SExpressionTester { @Test public void testLambdaExpressionGetLambdaExpression() { String expected = "(LAMBDA)"; - LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getUniqueInstance()), null); + LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getInstance()), null); assertSExpressionMatchesString(expected, lambda.getLambdaExpression()); } @@ -99,9 +99,9 @@ public class SExpressionTester { @Test public void testLambdaExpressionGetFunction() { String expected = "(LAMBDA)"; - UserDefinedFunction function = new UserDefinedFunction(expected, Nil.getUniqueInstance(), - Nil.getUniqueInstance()); - LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getUniqueInstance()), + UserDefinedFunction function = new UserDefinedFunction(expected, Nil.getInstance(), + Nil.getInstance()); + LambdaExpression lambda = new LambdaExpression(new Cons(new Symbol("lambda"), Nil.getInstance()), function); assertEquals(function, lambda.getFunction()); @@ -109,28 +109,28 @@ public class SExpressionTester { @Test public void testCarOfNilIsNil() { - assertEquals(Nil.getUniqueInstance().getCar(), Nil.getUniqueInstance()); + assertEquals(Nil.getInstance().getCar(), Nil.getInstance()); } @Test public void testCdrOfNilIsNil() { - assertEquals(Nil.getUniqueInstance().getCdr(), Nil.getUniqueInstance()); + assertEquals(Nil.getInstance().getCdr(), Nil.getInstance()); } @Test public void afterSettingCarOfNil_ShouldStillBeNil() { - Cons nil = Nil.getUniqueInstance(); + Cons nil = Nil.getInstance(); nil.setCar(new LispNumber("2")); - assertEquals(nil.getCar(), Nil.getUniqueInstance()); + assertEquals(nil.getCar(), Nil.getInstance()); } @Test public void afterSettingCdrOfNil_ShouldStillBeNil() { - Cons nil = Nil.getUniqueInstance(); + Cons nil = Nil.getInstance(); nil.setCdr(new LispNumber("2")); - assertEquals(nil.getCdr(), Nil.getUniqueInstance()); + assertEquals(nil.getCdr(), Nil.getInstance()); } @Test diff --git a/test/table/SymbolTableTester.java b/test/table/SymbolTableTester.java index 6791364..015c62f 100644 --- a/test/table/SymbolTableTester.java +++ b/test/table/SymbolTableTester.java @@ -35,8 +35,8 @@ public class SymbolTableTester { @Test public void redefineSymbolValue() { symbolTable.put("symbol", Symbol.T); - symbolTable.put("symbol", Nil.getUniqueInstance()); - assertEquals(symbolTable.get("symbol"), Nil.getUniqueInstance()); + symbolTable.put("symbol", Nil.getInstance()); + assertEquals(symbolTable.get("symbol"), Nil.getInstance()); } @Test diff --git a/test/testutil/SExpressionTypeAssertions.java b/test/testutil/SExpressionTypeAssertions.java index 6d8acf8..9b8126c 100644 --- a/test/testutil/SExpressionTypeAssertions.java +++ b/test/testutil/SExpressionTypeAssertions.java @@ -18,7 +18,7 @@ public final class SExpressionTypeAssertions { } public static void assertNil(SExpression sExpression) { - assertEquals(sExpression, Nil.getUniqueInstance()); + assertEquals(sExpression, Nil.getInstance()); assertTrue(sExpression.atomp()); assertFalse(sExpression.consp());