Convert predicates to kotlin

This commit is contained in:
Mike Cifelli 2018-11-04 08:34:07 -05:00
parent 8bc0ae744f
commit add24979d5
22 changed files with 247 additions and 291 deletions

View File

@ -1,28 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
@FunctionNames({ "ATOM", "ATOM?" })
public class ATOM extends LispFunction {
private ArgumentValidator argumentValidator;
public ATOM(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setExactNumberOfArguments(1);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
SExpression argument = argumentList.getFirst();
return argument.isAtom() ? Symbol.Companion.getT() : Nil.INSTANCE;
}
}

View File

@ -0,0 +1,24 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.Nil
import sexpression.SExpression
import sexpression.Symbol
@FunctionNames("ATOM", "ATOM?")
class Atom(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setExactNumberOfArguments(1)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
val argument = argumentList.first
return if (argument.isAtom) Symbol.T else Nil
}
}

View File

@ -1,54 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
@FunctionNames({ "EQ", "EQ?" })
public class EQ extends LispFunction {
private ArgumentValidator argumentValidator;
public EQ(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setExactNumberOfArguments(2);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
Cons rest = (Cons) argumentList.getRest();
SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = rest.getFirst();
return eq(firstArgument, secondArgument);
}
private SExpression eq(SExpression firstArgument, SExpression secondArgument) {
if (isAtomPair(firstArgument, secondArgument))
return atomEq(firstArgument, secondArgument);
return listEq(firstArgument, secondArgument);
}
private boolean isAtomPair(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.isAtom() && secondArgument.isAtom();
}
private SExpression atomEq(SExpression firstArgument, SExpression secondArgument) {
return isEq(firstArgument, secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
}
private boolean isEq(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.toString().equals(secondArgument.toString());
}
private SExpression listEq(SExpression firstArgument, SExpression secondArgument) {
return (firstArgument == secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
}
}

View File

@ -1,39 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
@FunctionNames({ "EQUAL", "EQUAL?" })
public class EQUAL extends LispFunction {
public static boolean isEqual(SExpression firstArgument, SExpression secondArgument) {
return firstArgument.toString().equals(secondArgument.toString());
}
private ArgumentValidator argumentValidator;
public EQUAL(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setExactNumberOfArguments(2);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
Cons rest = (Cons) argumentList.getRest();
SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = rest.getFirst();
return equal(firstArgument, secondArgument);
}
private SExpression equal(SExpression firstArgument, SExpression secondArgument) {
return isEqual(firstArgument, secondArgument) ? Symbol.Companion.getT() : Nil.INSTANCE;
}
}

View File

@ -0,0 +1,45 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.Nil
import sexpression.SExpression
import sexpression.Symbol.Companion.T
@FunctionNames("EQ", "EQ?")
class Eq(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setExactNumberOfArguments(2)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
val rest = argumentList.rest as Cons
val firstArgument = argumentList.first
val secondArgument = rest.first
return eq(firstArgument, secondArgument)
}
private fun eq(firstArgument: SExpression, secondArgument: SExpression) =
if (isAtomPair(firstArgument, secondArgument))
atomEq(firstArgument, secondArgument)
else
listEq(firstArgument, secondArgument)
private fun isAtomPair(firstArgument: SExpression, secondArgument: SExpression) =
firstArgument.isAtom && secondArgument.isAtom
private fun atomEq(firstArgument: SExpression, secondArgument: SExpression) =
if (isEq(firstArgument, secondArgument)) T else Nil
private fun isEq(firstArgument: SExpression, secondArgument: SExpression) =
firstArgument.toString() == secondArgument.toString()
private fun listEq(firstArgument: SExpression, secondArgument: SExpression) =
if (firstArgument === secondArgument) T else Nil
}

View File

@ -0,0 +1,36 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.Nil
import sexpression.SExpression
import sexpression.Symbol.Companion.T
@FunctionNames("EQUAL", "EQUAL?")
class Equal(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setExactNumberOfArguments(2)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
val rest = argumentList.rest as Cons
val firstArgument = argumentList.first
val secondArgument = rest.first
return equal(firstArgument, secondArgument)
}
private fun equal(firstArgument: SExpression, secondArgument: SExpression) =
if (isEqual(firstArgument, secondArgument)) T else Nil
companion object {
fun isEqual(firstArgument: SExpression, secondArgument: SExpression) =
firstArgument.toString() == secondArgument.toString()
}
}

View File

@ -1,27 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
@FunctionNames({ "LISTP", "LIST?" })
public class LISTP extends LispFunction {
private ArgumentValidator argumentValidator;
public LISTP(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setExactNumberOfArguments(1);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
return argumentList.getFirst().isList() ? Symbol.Companion.getT() : Nil.INSTANCE;
}
}

View File

@ -0,0 +1,23 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.Nil
import sexpression.SExpression
import sexpression.Symbol.Companion.T
@FunctionNames("LISTP", "LIST?")
class Listp(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setExactNumberOfArguments(1)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
return if (argumentList.first.isList) T else Nil
}
}

View File

@ -1,27 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import sexpression.Cons;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
@FunctionNames({ "NULL", "NULL?" })
public class NULL extends LispFunction {
private ArgumentValidator argumentValidator;
public NULL(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setExactNumberOfArguments(1);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
return argumentList.getFirst().isNull() ? Symbol.Companion.getT() : Nil.INSTANCE;
}
}

View File

@ -1,54 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import recursion.TailCall;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall;
@FunctionNames({ ">" })
public class NUMERIC_GREATER extends LispFunction {
private ArgumentValidator argumentValidator;
public NUMERIC_GREATER(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
return callTailRecursive(argumentList).invoke();
}
private TailCall<SExpression> callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.isNull())
return done(Symbol.Companion.getT());
SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = remainingArguments.getFirst();
LispNumber number1 = (LispNumber) firstArgument;
LispNumber number2 = (LispNumber) secondArgument;
if (!isFirstGreater(number1, number2))
return done(Nil.INSTANCE);
return tailCall(() -> callTailRecursive(remainingArguments));
}
private boolean isFirstGreater(LispNumber number1, LispNumber number2) {
return number1.getValue().compareTo(number2.getValue()) > 0;
}
}

View File

@ -1,54 +0,0 @@
package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import recursion.TailCall;
import sexpression.Cons;
import sexpression.LispNumber;
import sexpression.Nil;
import sexpression.SExpression;
import sexpression.Symbol;
import static recursion.TailCalls.done;
import static recursion.TailCalls.tailCall;
@FunctionNames({ "<" })
public class NUMERIC_LESS extends LispFunction {
private ArgumentValidator argumentValidator;
public NUMERIC_LESS(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setMinimumNumberOfArguments(1);
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
return callTailRecursive(argumentList).invoke();
}
private TailCall<SExpression> callTailRecursive(Cons argumentList) {
Cons remainingArguments = (Cons) argumentList.getRest();
if (remainingArguments.isNull())
return done(Symbol.Companion.getT());
SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = remainingArguments.getFirst();
LispNumber number1 = (LispNumber) firstArgument;
LispNumber number2 = (LispNumber) secondArgument;
if (!isFirstLesser(number1, number2))
return done(Nil.INSTANCE);
return tailCall(() -> callTailRecursive(remainingArguments));
}
private boolean isFirstLesser(LispNumber number1, LispNumber number2) {
return number1.getValue().compareTo(number2.getValue()) < 0;
}
}

View File

@ -0,0 +1,23 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.Nil
import sexpression.SExpression
import sexpression.Symbol.Companion.T
@FunctionNames("NULL", "NULL?")
class Null(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setExactNumberOfArguments(1)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
return if (argumentList.first.isNull) T else Nil
}
}

View File

@ -0,0 +1,42 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.LispNumber
import sexpression.Nil
import sexpression.SExpression
import sexpression.Symbol.Companion.T
@FunctionNames(">")
class NumericGreater(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setMinimumNumberOfArguments(1)
setEveryArgumentExpectedType(LispNumber::class.java)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
return callTailRecursive(argumentList)
}
private tailrec fun callTailRecursive(argumentList: Cons): SExpression {
val remainingArguments = argumentList.rest as Cons
if (remainingArguments.isNull)
return T
val firstArgument = argumentList.first
val secondArgument = remainingArguments.first
val number1 = firstArgument as LispNumber
val number2 = secondArgument as LispNumber
return if (number1.value > number2.value)
callTailRecursive(remainingArguments)
else
Nil
}
}

View File

@ -0,0 +1,46 @@
package function.builtin.predicate
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import recursion.TailCall
import sexpression.Cons
import sexpression.LispNumber
import sexpression.Nil
import sexpression.SExpression
import recursion.TailCalls.done
import recursion.TailCalls.tailCall
import sexpression.Symbol.Companion.T
@FunctionNames("<")
class NumericLess(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setMinimumNumberOfArguments(1)
setEveryArgumentExpectedType(LispNumber::class.java)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
return callTailRecursive(argumentList)
}
private tailrec fun callTailRecursive(argumentList: Cons): SExpression {
val remainingArguments = argumentList.rest as Cons
if (remainingArguments.isNull)
return T
val firstArgument = argumentList.first
val secondArgument = remainingArguments.first
val number1 = firstArgument as LispNumber
val number2 = secondArgument as LispNumber
return if (number1.value < number2.value)
callTailRecursive(remainingArguments)
else
Nil
}
}

View File

@ -4,7 +4,7 @@ import function.ArgumentValidator
import function.FunctionNames import function.FunctionNames
import function.LispSpecialFunction import function.LispSpecialFunction
import function.builtin.Eval.Companion.eval import function.builtin.Eval.Companion.eval
import function.builtin.predicate.EQUAL.isEqual import function.builtin.predicate.Equal.Companion.isEqual
import sexpression.Cons import sexpression.Cons
import sexpression.Nil import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class ATOMTest extends SymbolAndFunctionCleaner { public class AtomTest extends SymbolAndFunctionCleaner {
@Test @Test
public void atomIsAtom() { public void atomIsAtom() {

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class EQTest extends SymbolAndFunctionCleaner { public class EqTest extends SymbolAndFunctionCleaner {
@Test @Test
public void eqWithEqualAtoms() { public void eqWithEqualAtoms() {

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class EQUALTest extends SymbolAndFunctionCleaner { public class EqualTest extends SymbolAndFunctionCleaner {
@Test @Test
public void equalWithTwoEqualAtoms() { public void equalWithTwoEqualAtoms() {

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class LISTPTest extends SymbolAndFunctionCleaner { public class ListpTest extends SymbolAndFunctionCleaner {
@Test @Test
public void listpWithList() { public void listpWithList() {

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class NULLTest extends SymbolAndFunctionCleaner { public class NullTest extends SymbolAndFunctionCleaner {
@Test @Test
public void nilIsNull() { public void nilIsNull() {

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class NUMERIC_GREATERTest extends SymbolAndFunctionCleaner { public class NumericGreaterTest extends SymbolAndFunctionCleaner {
@Test @Test
public void greaterThanWithOneNumber_ReturnsT() { public void greaterThanWithOneNumber_ReturnsT() {

View File

@ -9,7 +9,7 @@ import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil; import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT; import static testutil.TypeAssertions.assertT;
public class NUMERIC_LESSTest extends SymbolAndFunctionCleaner { public class NumericLessTest extends SymbolAndFunctionCleaner {
@Test @Test
public void lessThanWithOneNumber_ReturnsT() { public void lessThanWithOneNumber_ReturnsT() {