Add modulo function
This commit is contained in:
parent
89b4c0804a
commit
6a4d19517e
|
@ -5,7 +5,7 @@ import sexpression.SExpression;
|
||||||
|
|
||||||
public abstract class LispFunction {
|
public abstract class LispFunction {
|
||||||
|
|
||||||
public abstract SExpression call(Cons argList);
|
public abstract SExpression call(Cons argumentList);
|
||||||
|
|
||||||
public boolean isArgumentListEvaluated() {
|
public boolean isArgumentListEvaluated() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package function.builtin.math;
|
||||||
|
|
||||||
|
import error.LispException;
|
||||||
|
import function.ArgumentValidator;
|
||||||
|
import function.FunctionNames;
|
||||||
|
import function.LispFunction;
|
||||||
|
import sexpression.Cons;
|
||||||
|
import sexpression.LispNumber;
|
||||||
|
import sexpression.SExpression;
|
||||||
|
|
||||||
|
@FunctionNames({ "MOD", "MODULO", "%" })
|
||||||
|
public class MODULO extends LispFunction {
|
||||||
|
|
||||||
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
public MODULO(String name) {
|
||||||
|
this.argumentValidator = new ArgumentValidator(name);
|
||||||
|
this.argumentValidator.setExactNumberOfArguments(2);
|
||||||
|
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SExpression call(Cons argumentList) {
|
||||||
|
argumentValidator.validate(argumentList);
|
||||||
|
LispNumber dividend = (LispNumber) argumentList.getFirst();
|
||||||
|
LispNumber divisor = (LispNumber) ((Cons) argumentList.getRest()).getFirst();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new LispNumber(dividend.getValue().mod(divisor.getValue()));
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
throw new ModulusNotPositiveException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ModulusNotPositiveException extends LispException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "modulus not positive";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import function.builtin.cons.LIST;
|
||||||
import function.builtin.cons.REST;
|
import function.builtin.cons.REST;
|
||||||
import function.builtin.math.DIVIDE;
|
import function.builtin.math.DIVIDE;
|
||||||
import function.builtin.math.MINUS;
|
import function.builtin.math.MINUS;
|
||||||
|
import function.builtin.math.MODULO;
|
||||||
import function.builtin.math.MULTIPLY;
|
import function.builtin.math.MULTIPLY;
|
||||||
import function.builtin.math.PLUS;
|
import function.builtin.math.PLUS;
|
||||||
import function.builtin.predicate.ATOM;
|
import function.builtin.predicate.ATOM;
|
||||||
|
@ -88,6 +89,7 @@ public class FunctionTable {
|
||||||
allBuiltIns.add(LISTP.class);
|
allBuiltIns.add(LISTP.class);
|
||||||
allBuiltIns.add(LOAD.class);
|
allBuiltIns.add(LOAD.class);
|
||||||
allBuiltIns.add(MINUS.class);
|
allBuiltIns.add(MINUS.class);
|
||||||
|
allBuiltIns.add(MODULO.class);
|
||||||
allBuiltIns.add(MULTIPLY.class);
|
allBuiltIns.add(MULTIPLY.class);
|
||||||
allBuiltIns.add(NULL.class);
|
allBuiltIns.add(NULL.class);
|
||||||
allBuiltIns.add(OR.class);
|
allBuiltIns.add(OR.class);
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class LispFunctionTest {
|
||||||
LispFunction lispFunction = new LispFunction() {
|
LispFunction lispFunction = new LispFunction() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class LispSpecialFunctionTest {
|
||||||
LispFunction lispFunction = new LispSpecialFunction() {
|
LispFunction lispFunction = new LispSpecialFunction() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package function.builtin.math;
|
||||||
|
|
||||||
|
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||||
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import function.ArgumentValidator.BadArgumentTypeException;
|
||||||
|
import function.ArgumentValidator.TooFewArgumentsException;
|
||||||
|
import function.ArgumentValidator.TooManyArgumentsException;
|
||||||
|
import function.builtin.math.MODULO.ModulusNotPositiveException;
|
||||||
|
import sexpression.LispNumber;
|
||||||
|
import testutil.SymbolAndFunctionCleaner;
|
||||||
|
|
||||||
|
public class MODULOTest extends SymbolAndFunctionCleaner {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mod() {
|
||||||
|
String input = "(mod 5 3)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void modulo() {
|
||||||
|
String input = "(modulo 11 7)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("4"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void moduloSymbol() {
|
||||||
|
String input = "(% 8 5)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("3"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendGreaterThanDivisor() {
|
||||||
|
String input = "(mod 21 19)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendLessThanDivisor() {
|
||||||
|
String input = "(mod 5 239)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("5"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendEqualToDivisor() {
|
||||||
|
String input = "(mod 5 5)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendMultipleOfDivisor() {
|
||||||
|
String input = "(mod 20 5)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void divisorOfOne() {
|
||||||
|
String input = "(mod 5 1)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendOfZero() {
|
||||||
|
String input = "(mod 0 2309)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void negativeDividend() {
|
||||||
|
String input = "(mod -23 25)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ModulusNotPositiveException.class)
|
||||||
|
public void divisorOfZero() {
|
||||||
|
String input = "(mod 5 0)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ModulusNotPositiveException.class)
|
||||||
|
public void negativeDivisor() {
|
||||||
|
String input = "(mod 5 -10)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
public void modWithNonNumber() {
|
||||||
|
evaluateString("(mod 'a 'b)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void modWithTooFewArguments() {
|
||||||
|
evaluateString("(mod 1)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void modWithTooManyArguments() {
|
||||||
|
evaluateString("(mod 1 2 3)");
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ public class FunctionTableTest {
|
||||||
public GoodFunction(String name) {}
|
public GoodFunction(String name) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ public class FunctionTableTest {
|
||||||
public static class BadFunction extends LispFunction {
|
public static class BadFunction extends LispFunction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public class FunctionTableTest {
|
||||||
public static class UglyFunction extends LispFunction {
|
public static class UglyFunction extends LispFunction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class FunctionTableTest {
|
||||||
return new LispFunction() {
|
return new LispFunction() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SExpression call(Cons argList) {
|
public SExpression call(Cons argumentList) {
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue