Started conversion to BigInteger for numbers

This commit is contained in:
Mike Cifelli 2016-12-25 13:56:24 -05:00
parent 68510ec1a8
commit 4b0c4b44a7
11 changed files with 48 additions and 38 deletions

View File

@ -1,5 +1,7 @@
package function.builtin; package function.builtin;
import java.math.BigInteger;
import function.LispFunction; import function.LispFunction;
import sexpression.*; import sexpression.*;
@ -26,7 +28,7 @@ public class DIVIDE extends LispFunction {
if (argRest.nullp()) { if (argRest.nullp()) {
// there is only one argument, so return the multiplicative // there is only one argument, so return the multiplicative
// inverse of the number // inverse of the number
return new LispNumber(1 / num1.getValue()); return new LispNumber(BigInteger.ONE.divide(num1.getValue()));
} }
SExpression argSecond = argRest.getCar(); SExpression argSecond = argRest.getCar();
@ -34,7 +36,7 @@ public class DIVIDE extends LispFunction {
// make sure that the next argument is a number as well // make sure that the next argument is a number as well
if (argSecond.numberp()) { if (argSecond.numberp()) {
LispNumber num2 = (LispNumber) argSecond; LispNumber num2 = (LispNumber) argSecond;
LispNumber quotient = new LispNumber(num1.getValue() / num2.getValue()); LispNumber quotient = new LispNumber(num1.getValue().divide(num2.getValue()));
SExpression argCddr = argRest.getCdr(); SExpression argCddr = argRest.getCdr();
if (argCddr.consp()) { if (argCddr.consp()) {

View File

@ -33,7 +33,7 @@ public class EQUALSP extends LispFunction {
if (secondArg.numberp()) { if (secondArg.numberp()) {
LispNumber num2 = (LispNumber) secondArg; LispNumber num2 = (LispNumber) secondArg;
if (num1.getValue() == num2.getValue()) { if (num1.getValue().equals(num2.getValue())) {
return call(argRest); return call(argRest);
} }

View File

@ -33,7 +33,7 @@ public class GREATERP extends LispFunction {
if (secondArg.numberp()) { if (secondArg.numberp()) {
LispNumber num2 = (LispNumber) secondArg; LispNumber num2 = (LispNumber) secondArg;
if (num1.getValue() > num2.getValue()) { if (num1.getValue().compareTo(num2.getValue()) > 0) {
return call(argRest); return call(argRest);
} }

View File

@ -1,5 +1,7 @@
package function.builtin; package function.builtin;
import java.math.BigInteger;
import function.LispFunction; import function.LispFunction;
import sexpression.*; import sexpression.*;
@ -12,15 +14,15 @@ public class LENGTH extends LispFunction {
* Returns the length of the given list. * Returns the length of the given list.
* *
* @param list * @param list
* the list to determine the length of * the list to determine the length of
* @return * @return the length of <code>list</code>
* the length of <code>list</code>
*/ */
public static int getLength(Cons list) { public static int getLength(Cons list) {
LENGTH lengthFunction = new LENGTH(); LENGTH lengthFunction = new LENGTH();
LispNumber length = lengthFunction.call(LIST.makeList(list)); LispNumber length = lengthFunction.call(LIST.makeList(list));
return length.getValue(); return length.getValue().intValue(); // TODO - return BigInteger when all built-ins use
// ArgumentValidator
} }
public LispNumber call(Cons argList) { public LispNumber call(Cons argList) {
@ -28,19 +30,17 @@ public class LENGTH extends LispFunction {
if (argList.nullp()) { if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList); Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList);
throw new RuntimeException("too few arguments given to LENGTH: " + throw new RuntimeException("too few arguments given to LENGTH: " + originalSExpr);
originalSExpr);
} }
SExpression argCar = argList.getCar(); SExpression argCar = argList.getCar();
SExpression argCdr = argList.getCdr(); SExpression argCdr = argList.getCdr();
// make sure we have received only one argument // make sure we have received only one argument
if (! argCdr.nullp()) { if (!argCdr.nullp()) {
Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList); Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList);
throw new RuntimeException("too many arguments given to LENGTH: " + throw new RuntimeException("too many arguments given to LENGTH: " + originalSExpr);
originalSExpr);
} }
// make sure that the argument is a list // make sure that the argument is a list
@ -48,17 +48,16 @@ public class LENGTH extends LispFunction {
Cons arg = (Cons) argCar; Cons arg = (Cons) argCar;
if (arg.nullp()) { if (arg.nullp()) {
return new LispNumber(0); return new LispNumber(BigInteger.ZERO);
} }
Cons cdr = LIST.makeList(arg.getCdr()); Cons cdr = LIST.makeList(arg.getCdr());
LispNumber cdrLength = call(cdr); LispNumber cdrLength = call(cdr);
return new LispNumber(1 + cdrLength.getValue()); return new LispNumber(BigInteger.ONE.add(cdrLength.getValue()));
} }
throw new RuntimeException("LENGTH: a proper list must not end with " + throw new RuntimeException("LENGTH: a proper list must not end with " + argCar);
argCar);
} }
} }

View File

@ -33,7 +33,7 @@ public class LESSP extends LispFunction {
if (secondArg.numberp()) { if (secondArg.numberp()) {
LispNumber num2 = (LispNumber) secondArg; LispNumber num2 = (LispNumber) secondArg;
if (num1.getValue() < num2.getValue()) { if (num1.getValue().compareTo(num2.getValue()) < 0) {
return call(argRest); return call(argRest);
} }

View File

@ -1,5 +1,7 @@
package function.builtin; package function.builtin;
import java.math.BigInteger;
import function.LispFunction; import function.LispFunction;
import sexpression.*; import sexpression.*;
@ -26,7 +28,7 @@ public class MINUS extends LispFunction {
if (argRest.nullp()) { if (argRest.nullp()) {
// there is only one argument, so return the additive // there is only one argument, so return the additive
// inverse of the number // inverse of the number
return new LispNumber(-num1.getValue()); return new LispNumber(BigInteger.ZERO.subtract(num1.getValue()));
} }
SExpression argSecond = argRest.getCar(); SExpression argSecond = argRest.getCar();
@ -34,7 +36,7 @@ public class MINUS extends LispFunction {
// make sure that the next argument is a number as well // make sure that the next argument is a number as well
if (argSecond.numberp()) { if (argSecond.numberp()) {
LispNumber num2 = (LispNumber) argSecond; LispNumber num2 = (LispNumber) argSecond;
LispNumber difference = new LispNumber(num1.getValue() - num2.getValue()); LispNumber difference = new LispNumber(num1.getValue().subtract(num2.getValue()));
SExpression argCddr = argRest.getCdr(); SExpression argCddr = argRest.getCdr();
if (argCddr.consp()) { if (argCddr.consp()) {

View File

@ -1,5 +1,7 @@
package function.builtin; package function.builtin;
import java.math.BigInteger;
import function.LispFunction; import function.LispFunction;
import sexpression.*; import sexpression.*;
@ -10,7 +12,7 @@ public class MULTIPLY extends LispFunction {
public LispNumber call(Cons argList) { public LispNumber call(Cons argList) {
if (argList.nullp()) { if (argList.nullp()) {
return new LispNumber(1); return new LispNumber(BigInteger.ONE);
} }
SExpression argFirst = argList.getCar(); SExpression argFirst = argList.getCar();
@ -20,7 +22,7 @@ public class MULTIPLY extends LispFunction {
LispNumber num1 = (LispNumber) argFirst; LispNumber num1 = (LispNumber) argFirst;
LispNumber num2 = call(argRest); LispNumber num2 = call(argRest);
return new LispNumber(num1.getValue() * num2.getValue()); return new LispNumber(num1.getValue().multiply(num2.getValue()));
} }
throw new RuntimeException("*: " + argFirst + " is not a number"); throw new RuntimeException("*: " + argFirst + " is not a number");

View File

@ -1,5 +1,7 @@
package function.builtin; package function.builtin;
import java.math.BigInteger;
import function.LispFunction; import function.LispFunction;
import sexpression.*; import sexpression.*;
@ -7,7 +9,7 @@ public class PLUS extends LispFunction {
public LispNumber call(Cons argList) { public LispNumber call(Cons argList) {
if (argList.nullp()) { if (argList.nullp()) {
return new LispNumber(0); return new LispNumber(BigInteger.ZERO);
} }
if (!argList.getCdr().listp()) if (!argList.getCdr().listp())
@ -20,7 +22,7 @@ public class PLUS extends LispFunction {
LispNumber num1 = (LispNumber) argFirst; LispNumber num1 = (LispNumber) argFirst;
LispNumber num2 = call(argRest); LispNumber num2 = call(argRest);
return new LispNumber(num1.getValue() + num2.getValue()); return new LispNumber(num1.getValue().add(num2.getValue()));
} }
throw new RuntimeException("+: " + argFirst + " is not a number"); throw new RuntimeException("+: " + argFirst + " is not a number");

View File

@ -1,5 +1,6 @@
package sexpression; package sexpression;
import java.math.BigInteger;
import java.text.MessageFormat; import java.text.MessageFormat;
import error.LispException; import error.LispException;
@ -7,20 +8,20 @@ import error.LispException;
@DisplayName("number") @DisplayName("number")
public class LispNumber extends Atom { public class LispNumber extends Atom {
private int value; private BigInteger value;
public LispNumber(String text) { public LispNumber(String text) {
super(text.replaceFirst("^0+(?!$)", "")); super(text.replaceFirst("^0+(?!$)", ""));
try { try {
this.value = Integer.parseInt(text); this.value = new BigInteger(text);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new InvalidNumberException(text); throw new InvalidNumberException(text);
} }
} }
public LispNumber(int value) { public LispNumber(BigInteger value) {
super(Integer.toString(value)); super(value.toString());
this.value = value; this.value = value;
} }
@ -29,7 +30,7 @@ public class LispNumber extends Atom {
return true; return true;
} }
public int getValue() { public BigInteger getValue() {
return value; return value;
} }

View File

@ -42,7 +42,7 @@ public class UserDefinedFunctionTester {
@Test @Test
public void oneArgumentFunction_ReturnsCorrectValue() { public void oneArgumentFunction_ReturnsCorrectValue() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
SExpression argument = new LispNumber(23); SExpression argument = new LispNumber("23");
Cons argumentList = new Cons(argument, Nil.getUniqueInstance()); Cons argumentList = new Cons(argument, Nil.getUniqueInstance());
assertSExpressionsMatch(argument, function.call(argumentList)); assertSExpressionsMatch(argument, function.call(argumentList));
@ -51,7 +51,7 @@ public class UserDefinedFunctionTester {
@Test(expected = TooManyArgumentsException.class) @Test(expected = TooManyArgumentsException.class)
public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() { public void oneArgumentFunction_ThrowsExceptionWithTooManyArguments() {
UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument(); UserDefinedFunction function = createOneArgumentFunctionThatReturnsArgument();
SExpression argument = new LispNumber(23); SExpression argument = new LispNumber("23");
Cons argumentList = new Cons(argument, new Cons(argument, Nil.getUniqueInstance())); Cons argumentList = new Cons(argument, new Cons(argument, Nil.getUniqueInstance()));
function.call(argumentList); function.call(argumentList);

View File

@ -2,6 +2,8 @@ package sexpression;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.math.BigInteger;
import org.junit.*; import org.junit.*;
import error.ErrorManager; import error.ErrorManager;
@ -35,7 +37,7 @@ public class SExpressionTester {
public void testNumberValueToString() { public void testNumberValueToString() {
String expected = "12"; String expected = "12";
assertSExpressionMatchesString(expected, new LispNumber(12)); assertSExpressionMatchesString(expected, new LispNumber("12"));
} }
@Test @Test
@ -55,7 +57,7 @@ public class SExpressionTester {
@Test @Test
public void testSimpleConsToString() { public void testSimpleConsToString() {
String expected = "(1)"; String expected = "(1)";
Cons cons = new Cons(new LispNumber(1), Nil.getUniqueInstance()); Cons cons = new Cons(new LispNumber("1"), Nil.getUniqueInstance());
assertSExpressionMatchesString(expected, cons); assertSExpressionMatchesString(expected, cons);
} }
@ -63,7 +65,7 @@ public class SExpressionTester {
@Test @Test
public void testComplexConsToString() { public void testComplexConsToString() {
String expected = "(1 A \"string\")"; String expected = "(1 A \"string\")";
Cons list = new Cons(new LispNumber(1), Cons list = new Cons(new LispNumber("1"),
new Cons(new Symbol("a"), new Cons(new Symbol("a"),
new Cons(new LispString("\"string\""), Nil.getUniqueInstance()))); new Cons(new LispString("\"string\""), Nil.getUniqueInstance())));
@ -118,7 +120,7 @@ public class SExpressionTester {
@Test @Test
public void afterSettingCarOfNil_ShouldStillBeNil() { public void afterSettingCarOfNil_ShouldStillBeNil() {
Cons nil = Nil.getUniqueInstance(); Cons nil = Nil.getUniqueInstance();
nil.setCar(new LispNumber(2)); nil.setCar(new LispNumber("2"));
assertEquals(nil.getCar(), Nil.getUniqueInstance()); assertEquals(nil.getCar(), Nil.getUniqueInstance());
} }
@ -126,15 +128,15 @@ public class SExpressionTester {
@Test @Test
public void afterSettingCdrOfNil_ShouldStillBeNil() { public void afterSettingCdrOfNil_ShouldStillBeNil() {
Cons nil = Nil.getUniqueInstance(); Cons nil = Nil.getUniqueInstance();
nil.setCdr(new LispNumber(2)); nil.setCdr(new LispNumber("2"));
assertEquals(nil.getCdr(), Nil.getUniqueInstance()); assertEquals(nil.getCdr(), Nil.getUniqueInstance());
} }
@Test @Test
public void testNumberValue() { public void testNumberValue() {
int value = 12; BigInteger value = new BigInteger("12");
LispNumber number = new LispNumber(String.valueOf(value)); LispNumber number = new LispNumber(value.toString());
assertEquals(number.getValue(), value); assertEquals(number.getValue(), value);
} }