Resolves #10 - The equality predicates have been refactored

This commit is contained in:
Mike Cifelli 2017-02-28 11:54:19 -05:00
parent 50a3f3be67
commit d2dfe23083
14 changed files with 178 additions and 71 deletions

View File

@ -0,0 +1,24 @@
---
Test
---
| script | lisp interpreter fixture |
| # | Object with multiple methods |
| show | evaluate |!-
(defun counter-class-multi ()
(let ((counter 0))
(lambda (msg)
(case msg
((:inc)
(setq counter (+ counter 1)))
((:dec)
(setq counter (- counter 1)))))))
-!|
| show | evaluate | (setq my-counter (counter-class-multi)) |
| check | evaluate | (funcall my-counter :inc) | 1 |
| check | evaluate | (funcall my-counter :inc) | 2 |
| check | evaluate | (funcall my-counter :inc) | 3 |
| check | evaluate | (funcall my-counter :dec) | 2 |
| check | evaluate | (funcall my-counter :dec) | 1 |
| check | evaluate | (funcall my-counter :dec) | 0 |

View File

@ -1,3 +1,4 @@
|LispInterpreter.MultipleMethodClosure||11:52:11 Tue, Feb 28, 2017|
|LispInterpreter.LexicalClosures||12:10:13 Mon, Feb 27, 2017| |LispInterpreter.LexicalClosures||12:10:13 Mon, Feb 27, 2017|
|LispInterpreter.TestClosure||11:24:27 Mon, Feb 27, 2017| |LispInterpreter.TestClosure||11:24:27 Mon, Feb 27, 2017|
|LispInterpreter.TestOne||09:26:08 Fri, Feb 24, 2017| |LispInterpreter.TestOne||09:26:08 Fri, Feb 24, 2017|

View File

@ -35,7 +35,11 @@ public class EQ extends LispFunction {
} }
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) { private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {
return (firstArgument.toString().equals(secondArgument.toString())) ? Symbol.T : Nil.getInstance(); return isEq(firstArgument, secondArgument) ? Symbol.T : Nil.getInstance();
}
private boolean isEq(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.toString().equals(secondArgument.toString());
} }
private SExpression listEq(SExpression firstArgument, SExpression secondArgument) { private SExpression listEq(SExpression firstArgument, SExpression secondArgument) {

View File

@ -25,9 +25,21 @@ public class EQUAL extends LispFunction {
SExpression firstArgument = argumentList.getFirst(); SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = rest.getFirst(); SExpression secondArgument = rest.getFirst();
if (!isListPair(firstArgument, secondArgument))
return equal(firstArgument, secondArgument); return equal(firstArgument, secondArgument);
}
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
if (isListPair(firstArgument, secondArgument))
return listEqual(firstArgument, secondArgument);
return atomEqual(firstArgument, secondArgument);
}
private boolean isListPair(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.isCons() && secondArgument.isCons();
}
private SExpression listEqual(SExpression firstArgument, SExpression secondArgument) {
Cons listOne = (Cons) firstArgument; Cons listOne = (Cons) firstArgument;
Cons listTwo = (Cons) secondArgument; Cons listTwo = (Cons) secondArgument;
SExpression listOneFirst = listOne.getFirst(); SExpression listOneFirst = listOne.getFirst();
@ -41,20 +53,8 @@ public class EQUAL extends LispFunction {
return logicalConjunction(firstEqual, restEqual); return logicalConjunction(firstEqual, restEqual);
} }
private boolean isListPair(SExpression firstArgument, SExpression secondArgument) { private Cons makeArgumentList(SExpression one, SExpression two) {
return firstArgument.isCons() && secondArgument.isCons(); return new Cons(one, LIST.makeList(two));
}
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
return isEqual(firstArgument, secondArgument) ? Symbol.T : Nil.getInstance();
}
private boolean isEqual(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.toString().equals(secondArgument.toString());
}
private Cons makeArgumentList(SExpression listOneFirst, SExpression listTwoFirst) {
return new Cons(listOneFirst, LIST.makeList(listTwoFirst));
} }
private SExpression logicalConjunction(SExpression firstEqual, SExpression restEqual) { private SExpression logicalConjunction(SExpression firstEqual, SExpression restEqual) {
@ -65,4 +65,12 @@ public class EQUAL extends LispFunction {
return (firstEqual == Symbol.T) && (restEqual == Symbol.T); return (firstEqual == Symbol.T) && (restEqual == Symbol.T);
} }
private SExpression atomEqual(SExpression firstArgument, SExpression secondArgument) {
return isEqual(firstArgument, secondArgument) ? Symbol.T : Nil.getInstance();
}
private boolean isEqual(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.toString().equals(secondArgument.toString());
}
} }

View File

@ -4,11 +4,11 @@ import function.*;
import sexpression.*; import sexpression.*;
@FunctionNames({ "=" }) @FunctionNames({ "=" })
public class EQUALSP extends LispFunction { public class NUMERIC_EQUAL extends LispFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
public EQUALSP() { public NUMERIC_EQUAL() {
this.argumentValidator = new ArgumentValidator("="); this.argumentValidator = new ArgumentValidator("=");
this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);

View File

@ -4,11 +4,11 @@ import function.*;
import sexpression.*; import sexpression.*;
@FunctionNames({ ">" }) @FunctionNames({ ">" })
public class GREATERP extends LispFunction { public class NUMERIC_GREATER extends LispFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
public GREATERP() { public NUMERIC_GREATER() {
this.argumentValidator = new ArgumentValidator(">"); this.argumentValidator = new ArgumentValidator(">");
this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);

View File

@ -4,11 +4,11 @@ import function.*;
import sexpression.*; import sexpression.*;
@FunctionNames({ "<" }) @FunctionNames({ "<" })
public class LESSP extends LispFunction { public class NUMERIC_LESS extends LispFunction {
private ArgumentValidator argumentValidator; private ArgumentValidator argumentValidator;
public LESSP() { public NUMERIC_LESS() {
this.argumentValidator = new ArgumentValidator("<"); this.argumentValidator = new ArgumentValidator("<");
this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);

View File

@ -46,16 +46,16 @@ public class FunctionTable {
allBuiltIns.add(DIVIDE.class); allBuiltIns.add(DIVIDE.class);
allBuiltIns.add(EQ.class); allBuiltIns.add(EQ.class);
allBuiltIns.add(EQUAL.class); allBuiltIns.add(EQUAL.class);
allBuiltIns.add(EQUALSP.class); allBuiltIns.add(NUMERIC_EQUAL.class);
allBuiltIns.add(EVAL.class); allBuiltIns.add(EVAL.class);
allBuiltIns.add(EXIT.class); allBuiltIns.add(EXIT.class);
allBuiltIns.add(FIRST.class); allBuiltIns.add(FIRST.class);
allBuiltIns.add(FUNCALL.class); allBuiltIns.add(FUNCALL.class);
allBuiltIns.add(GREATERP.class); allBuiltIns.add(NUMERIC_GREATER.class);
allBuiltIns.add(IF.class); allBuiltIns.add(IF.class);
allBuiltIns.add(LAMBDA.class); allBuiltIns.add(LAMBDA.class);
allBuiltIns.add(LENGTH.class); allBuiltIns.add(LENGTH.class);
allBuiltIns.add(LESSP.class); allBuiltIns.add(NUMERIC_LESS.class);
allBuiltIns.add(LET.class); allBuiltIns.add(LET.class);
allBuiltIns.add(LIST.class); allBuiltIns.add(LIST.class);
allBuiltIns.add(LISTP.class); allBuiltIns.add(LISTP.class);

View File

@ -10,28 +10,63 @@ import function.ArgumentValidator.*;
public class EQTester { public class EQTester {
@Test @Test
public void testEqWithEqualAtoms() { public void eqWithEqualAtoms() {
String input = "(eq 1 1)"; String input = "(eq 1 1)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testEqWithUnequalAtoms() { public void eqWithUnequalAtoms() {
String input = "(eq 1 2)"; String input = "(eq 1 2)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqWithAtomAndList() { public void eqWithTwoEqualNumbers() {
String input = "(eq -4 -4)";
assertT(evaluateString(input));
}
@Test
public void eqWithTwoUnequalNumbers() {
String input = "(eq +5 +7)";
assertNil(evaluateString(input));
}
@Test
public void eqWithTwoEqualStrings() {
String input = "(eq \"potato\" \"potato\")";
assertT(evaluateString(input));
}
@Test
public void eqWithTwoUnequalStrings() {
String input = "(eq \"tomato\" \"potato\")";
assertNil(evaluateString(input));
}
@Test
public void eqWithTwoDifferentCasedStrings() {
String input = "(eq \"Potato\" \"potato\")";
assertNil(evaluateString(input));
}
@Test
public void eqWithAtomAndList() {
String input = "(eq 1 '(2))"; String input = "(eq 1 '(2))";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqWithSameList() { public void eqWithSameList() {
String initializeL1 = "(setf l1 '(1 2 3))"; String initializeL1 = "(setf l1 '(1 2 3))";
String initializeL2 = "(setf l2 l1)"; String initializeL2 = "(setf l2 l1)";
String input = "(eq l1 l2)"; String input = "(eq l1 l2)";
@ -43,26 +78,26 @@ public class EQTester {
} }
@Test @Test
public void testEqWithEqualLists() { public void eqWithEqualLists() {
String input = "(eq '(1 2) '(1 2))"; String input = "(eq '(1 2) '(1 2))";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqWithUnequalLists() { public void eqWithUnequalLists() {
String input = "(eq '(1 2) '(3 4))"; String input = "(eq '(1 2) '(3 4))";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test(expected = TooManyArgumentsException.class) @Test(expected = TooManyArgumentsException.class)
public void testEqWithTooManyArguments() { public void eqWithTooManyArguments() {
evaluateString("(eq 'one 'two 'three)"); evaluateString("(eq 'one 'two 'three)");
} }
@Test(expected = TooFewArgumentsException.class) @Test(expected = TooFewArgumentsException.class)
public void testEqWithTooFewArguments() { public void eqWithTooFewArguments() {
evaluateString("(eq 'one)"); evaluateString("(eq 'one)");
} }

View File

@ -10,61 +10,96 @@ import function.ArgumentValidator.*;
public class EQUALTester { public class EQUALTester {
@Test @Test
public void testEqualWithTwoEqualAtoms() { public void equalWithTwoEqualAtoms() {
String input = "(equal 'a 'a)"; String input = "(equal 'a 'a)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testEqualWithTwoUnequalAtoms() { public void equalWithTwoUnequalAtoms() {
String input = "(equal 'a 'b)"; String input = "(equal 'a 'b)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqualWithAtomAndList() { public void equalWithTwoEqualNumbers() {
String input = "(equal -4 -4)";
assertT(evaluateString(input));
}
@Test
public void equalWithTwoUnequalNumbers() {
String input = "(equal +5 +7)";
assertNil(evaluateString(input));
}
@Test
public void equalWithTwoEqualStrings() {
String input = "(equal \"potato\" \"potato\")";
assertT(evaluateString(input));
}
@Test
public void equalWithTwoUnequalStrings() {
String input = "(equal \"tomato\" \"potato\")";
assertNil(evaluateString(input));
}
@Test
public void equalWithTwoDifferentCasedStrings() {
String input = "(equal \"Potato\" \"potato\")";
assertNil(evaluateString(input));
}
@Test
public void equalWithAtomAndList() {
String input = "(equal \"string\" '(m i k e))"; String input = "(equal \"string\" '(m i k e))";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqualWithListAndAtom() { public void equalWithListAndAtom() {
String input = "(equal '(m i k e) \"string\")"; String input = "(equal '(m i k e) \"string\")";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqualWithTwoEqualLists() { public void equalWithTwoEqualLists() {
String input = "(equal '(1 2 3) '(1 2 3))"; String input = "(equal '(1 2 3) '(1 2 3))";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testEqualWithTwoUnequalLists() { public void equalWithTwoUnequalLists() {
String input = "(equal '(1 2 3) '(1 3 3))"; String input = "(equal '(1 2 3) '(1 3 3))";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqualWithTwoEqualNestedLists() { public void equalWithTwoEqualNestedLists() {
String input = "(equal '(1 ((2) 3)) '(1 ((2) 3)))"; String input = "(equal '(1 ((2) 3)) '(1 ((2) 3)))";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test(expected = TooManyArgumentsException.class) @Test(expected = TooManyArgumentsException.class)
public void testEqualWithTooManyArguments() { public void equalWithTooManyArguments() {
evaluateString("(equal 1 2 3)"); evaluateString("(equal 1 2 3)");
} }
@Test(expected = TooFewArgumentsException.class) @Test(expected = TooFewArgumentsException.class)
public void testEqualWithTooFewArguments() { public void equalWithTooFewArguments() {
evaluateString("(equal 1)"); evaluateString("(equal 1)");
} }

View File

@ -10,22 +10,22 @@ import function.ArgumentValidator.*;
public class LISTPTester { public class LISTPTester {
@Test @Test
public void testListpWithList_ReturnsT() { public void listpWithList() {
assertT(evaluateString("(listp '(1))")); assertT(evaluateString("(listp '(1))"));
} }
@Test @Test
public void testListWithNonList_ReturnsNil() { public void listpWithNonList() {
assertNil(evaluateString("(listp 1)")); assertNil(evaluateString("(listp 1)"));
} }
@Test(expected = TooFewArgumentsException.class) @Test(expected = TooFewArgumentsException.class)
public void testListpWithTooFewArguments() { public void listpWithTooFewArguments() {
evaluateString("(listp)"); evaluateString("(listp)");
} }
@Test(expected = TooManyArgumentsException.class) @Test(expected = TooManyArgumentsException.class)
public void testListpWithTooManyArguments() { public void listpWithTooManyArguments() {
evaluateString("(listp '() '())"); evaluateString("(listp '() '())");
} }

View File

@ -7,50 +7,50 @@ import org.junit.Test;
import function.ArgumentValidator.*; import function.ArgumentValidator.*;
public class EQUALSPTester { public class NUMERIC_EQUALTester {
@Test @Test
public void testEqualspWithOneNumber() { public void numericEqualWithOneNumber() {
String input = "(= 1)"; String input = "(= 1)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testEqualspWithEqualNumbers() { public void numericEqualWithEqualNumbers() {
String input = "(= 1 1)"; String input = "(= 1 1)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testEqualspWithNonEqualNumbers() { public void numericEqualWithNonEqualNumbers() {
String input = "(= 1 2)"; String input = "(= 1 2)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testEqualspWithManyEqualNumbers() { public void numericEqualWithManyEqualNumbers() {
String input = "(= 4 4 4 4 4 4 4 4 4 4)"; String input = "(= 4 4 4 4 4 4 4 4 4 4)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testEqualspWithManyNonEqualNumbers() { public void numericEqualWithManyNonEqualNumbers() {
String input = "(= 4 4 4 4 5 4 4 4 4 4)"; String input = "(= 4 4 4 4 5 4 4 4 4 4)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test(expected = BadArgumentTypeException.class) @Test(expected = BadArgumentTypeException.class)
public void testEqualspWithNonNumbers() { public void numericEqualWithNonNumbers() {
evaluateString("(= 'x 'x)"); evaluateString("(= 'x 'x)");
} }
@Test(expected = TooFewArgumentsException.class) @Test(expected = TooFewArgumentsException.class)
public void testEqualspWithTooFewArguments() { public void numericEqualWithTooFewArguments() {
evaluateString("(=)"); evaluateString("(=)");
} }

View File

@ -7,50 +7,50 @@ import org.junit.Test;
import function.ArgumentValidator.*; import function.ArgumentValidator.*;
public class GREATERPTester { public class NUMERIC_GREATERTester {
@Test @Test
public void testGreaterpWithOneNumber_ReturnsT() { public void greaterThanWithOneNumber_ReturnsT() {
String input = "(> 1)"; String input = "(> 1)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testGreaterpWithTwoNumbers_ReturnsNil() { public void greaterThanWithTwoNumbers_ReturnsNil() {
String input = "(> 1 2)"; String input = "(> 1 2)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testGreaterpWithTwoNumbers_ReturnsT() { public void greaterThanWithTwoNumbers_ReturnsT() {
String input = "(> 3 2)"; String input = "(> 3 2)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testGreaterpWithManyNumbers_ReturnsNil() { public void greaterThanWithManyNumbers_ReturnsNil() {
String input = "(> 4 3 2 5 1)"; String input = "(> 4 3 2 5 1)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testGreaterpWithManyNumbers_ReturnsT() { public void greaterThanWithManyNumbers() {
String input = "(> 4 3 2 1 0)"; String input = "(> 4 3 2 1 0)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test(expected = BadArgumentTypeException.class) @Test(expected = BadArgumentTypeException.class)
public void testGreaterpWithNonNumbers() { public void greaterThanWithNonNumbers() {
evaluateString("(> 'x 'x)"); evaluateString("(> 'x 'x)");
} }
@Test(expected = TooFewArgumentsException.class) @Test(expected = TooFewArgumentsException.class)
public void testGreaterpWithTooFewArguments() { public void greaterThanWithTooFewArguments() {
evaluateString("(>)"); evaluateString("(>)");
} }

View File

@ -7,50 +7,50 @@ import org.junit.Test;
import function.ArgumentValidator.*; import function.ArgumentValidator.*;
public class LESSPTester { public class NUMERIC_LESSTester {
@Test @Test
public void testLesspWithOneNumber_ReturnsT() { public void lessThanWithOneNumber_ReturnsT() {
String input = "(< 1)"; String input = "(< 1)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testLesspWithTwoNumbers_ReturnsNil() { public void lessThanWithTwoNumbers_ReturnsNil() {
String input = "(< 2 1)"; String input = "(< 2 1)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testLesspWithTwoNumbers_ReturnsT() { public void lessThanWithTwoNumbers_ReturnsT() {
String input = "(< 2 3)"; String input = "(< 2 3)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test @Test
public void testLesspWithManyNumbers_ReturnsNil() { public void lessThanWithManyNumbers_ReturnsNil() {
String input = "(< 4 3 2 5 1)"; String input = "(< 4 3 2 5 1)";
assertNil(evaluateString(input)); assertNil(evaluateString(input));
} }
@Test @Test
public void testLesspWithManyNumbers_ReturnsT() { public void lessThanWithManyNumbers_ReturnsT() {
String input = "(< 0 1 2 3 4)"; String input = "(< 0 1 2 3 4)";
assertT(evaluateString(input)); assertT(evaluateString(input));
} }
@Test(expected = BadArgumentTypeException.class) @Test(expected = BadArgumentTypeException.class)
public void testLesspWithNonNumbers() { public void lessThanWithNonNumbers() {
evaluateString("(< '(1) '(2))"); evaluateString("(< '(1) '(2))");
} }
@Test(expected = TooFewArgumentsException.class) @Test(expected = TooFewArgumentsException.class)
public void testLesspWithTooFewArguments() { public void lessThanWithTooFewArguments() {
evaluateString("(<)"); evaluateString("(<)");
} }