Convert the argument validator to kotlin
This commit is contained in:
parent
d902328a56
commit
3f82b473b4
2
pom.xml
2
pom.xml
|
@ -10,7 +10,7 @@
|
|||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.version>1.2.60</kotlin.version>
|
||||
<kotlin.version>1.2.70</kotlin.version>
|
||||
<junit5.version>5.2.0</junit5.version>
|
||||
<skipTests>false</skipTests>
|
||||
</properties>
|
||||
|
|
|
@ -1,234 +0,0 @@
|
|||
package function;
|
||||
|
||||
import error.LispException;
|
||||
import sexpression.Cons;
|
||||
import sexpression.DisplayName;
|
||||
import sexpression.SExpression;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static function.builtin.cons.LENGTH.getLength;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
public class ArgumentValidator {
|
||||
|
||||
private Class<? extends SExpression> firstArgumentType;
|
||||
private Class<? extends SExpression> trailingArgumentType;
|
||||
private Class<? extends SExpression> excludedFirstArgumentType;
|
||||
private Class<? extends SExpression> excludedTrailingArgumentType;
|
||||
private String functionName;
|
||||
private BigInteger maximumNumberOfArguments;
|
||||
private BigInteger minimumNumberOfArguments;
|
||||
|
||||
public ArgumentValidator(String functionName) {
|
||||
this.firstArgumentType = SExpression.class;
|
||||
this.trailingArgumentType = SExpression.class;
|
||||
this.excludedFirstArgumentType = null;
|
||||
this.excludedTrailingArgumentType = null;
|
||||
this.functionName = functionName;
|
||||
this.minimumNumberOfArguments = null;
|
||||
this.maximumNumberOfArguments = null;
|
||||
}
|
||||
|
||||
public void setFirstArgumentExpectedType(Class<? extends SExpression> argumentType) {
|
||||
this.firstArgumentType = argumentType;
|
||||
}
|
||||
|
||||
public void setTrailingArgumentExpectedType(Class<? extends SExpression> argumentType) {
|
||||
this.trailingArgumentType = argumentType;
|
||||
}
|
||||
|
||||
public void setEveryArgumentExpectedType(Class<? extends SExpression> argumentType) {
|
||||
this.firstArgumentType = argumentType;
|
||||
this.trailingArgumentType = argumentType;
|
||||
}
|
||||
|
||||
public void setFirstArgumentExcludedType(Class<? extends SExpression> argumentType) {
|
||||
this.excludedFirstArgumentType = argumentType;
|
||||
}
|
||||
|
||||
public void setTrailingArgumentExcludedType(Class<? extends SExpression> argumentType) {
|
||||
this.excludedTrailingArgumentType = argumentType;
|
||||
}
|
||||
|
||||
public void setEveryArgumentExcludedType(Class<? extends SExpression> argumentType) {
|
||||
this.excludedFirstArgumentType = argumentType;
|
||||
this.excludedTrailingArgumentType = argumentType;
|
||||
}
|
||||
|
||||
public void setMaximumNumberOfArguments(int maximumNumberOfArguments) {
|
||||
this.maximumNumberOfArguments = BigInteger.valueOf(maximumNumberOfArguments);
|
||||
}
|
||||
|
||||
public void setMinimumNumberOfArguments(int minimumNumberOfArguments) {
|
||||
this.minimumNumberOfArguments = BigInteger.valueOf(minimumNumberOfArguments);
|
||||
}
|
||||
|
||||
public void setExactNumberOfArguments(int exactNumberOfArguments) {
|
||||
this.minimumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments);
|
||||
this.maximumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments);
|
||||
}
|
||||
|
||||
public void validate(Cons argumentList) {
|
||||
validateListNotDotted(argumentList);
|
||||
validateListLength(argumentList);
|
||||
validateArgumentTypes(argumentList);
|
||||
}
|
||||
|
||||
private void validateListNotDotted(Cons argumentList) {
|
||||
SExpression next = argumentList.getRest();
|
||||
|
||||
for (Cons current = argumentList; next.isCons(); next = current.getRest())
|
||||
current = (Cons) next;
|
||||
|
||||
if (!next.isNull())
|
||||
throw new DottedArgumentListException(functionName, argumentList);
|
||||
}
|
||||
|
||||
private void validateListLength(Cons argumentList) {
|
||||
if (containsTooFewArguments(argumentList))
|
||||
throw new TooFewArgumentsException(functionName, argumentList);
|
||||
else if (containsTooManyArguments(argumentList))
|
||||
throw new TooManyArgumentsException(functionName, argumentList);
|
||||
}
|
||||
|
||||
private boolean containsTooFewArguments(Cons argumentList) {
|
||||
return isMinimum() && isLengthLessThanMinimum(argumentList);
|
||||
}
|
||||
|
||||
private boolean isMinimum() {
|
||||
return minimumNumberOfArguments != null;
|
||||
}
|
||||
|
||||
private boolean isLengthLessThanMinimum(Cons argumentList) {
|
||||
return getLength(argumentList).compareTo(minimumNumberOfArguments) < 0;
|
||||
}
|
||||
|
||||
private boolean containsTooManyArguments(Cons argumentList) {
|
||||
return isMaximum() && isLengthGreaterThanMaximum(argumentList);
|
||||
}
|
||||
|
||||
private boolean isMaximum() {
|
||||
return maximumNumberOfArguments != null;
|
||||
}
|
||||
|
||||
private boolean isLengthGreaterThanMaximum(Cons argumentList) {
|
||||
return getLength(argumentList).compareTo(maximumNumberOfArguments) > 0;
|
||||
}
|
||||
|
||||
private void validateArgumentTypes(Cons argumentList) {
|
||||
validateFirstArgument(argumentList);
|
||||
validateTrailingArguments(argumentList);
|
||||
}
|
||||
|
||||
private void validateFirstArgument(Cons argumentList) {
|
||||
if (!isFirstArgumentValid(argumentList))
|
||||
throw new BadArgumentTypeException(functionName, argumentList.getFirst(), firstArgumentType);
|
||||
}
|
||||
|
||||
private boolean isFirstArgumentValid(Cons argumentList) {
|
||||
return argumentList.isNull() || isExpectedFirstArgumentType(argumentList.getFirst());
|
||||
}
|
||||
|
||||
private boolean isExpectedFirstArgumentType(SExpression firstArgument) {
|
||||
return firstArgumentType.isInstance(firstArgument) && !isExcludedFirstArgumentType(firstArgument);
|
||||
}
|
||||
|
||||
private boolean isExcludedFirstArgumentType(SExpression firstArgument) {
|
||||
return excludedFirstArgumentType != null && excludedFirstArgumentType.isInstance(firstArgument);
|
||||
}
|
||||
|
||||
private void validateTrailingArguments(Cons argumentList) {
|
||||
for (Cons cons = (Cons) argumentList.getRest(); !cons.isNull(); cons = (Cons) cons.getRest())
|
||||
if (!isExpectedTrailingArgumentType(cons.getFirst()))
|
||||
throw new BadArgumentTypeException(functionName, cons.getFirst(), trailingArgumentType);
|
||||
}
|
||||
|
||||
private boolean isExpectedTrailingArgumentType(SExpression trailingArgument) {
|
||||
return trailingArgumentType.isInstance(trailingArgument) && !isExcludedTrailingArgumentType(trailingArgument);
|
||||
}
|
||||
|
||||
private boolean isExcludedTrailingArgumentType(SExpression trailingArgument) {
|
||||
return excludedTrailingArgumentType != null && excludedTrailingArgumentType.isInstance(trailingArgument);
|
||||
}
|
||||
|
||||
public static class TooFewArgumentsException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String functionName;
|
||||
private Cons argumentList;
|
||||
|
||||
public TooFewArgumentsException(String functionName, Cons argumentList) {
|
||||
this.functionName = functionName;
|
||||
this.argumentList = argumentList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return format("too few arguments given to {0}: {1}", functionName, argumentList);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TooManyArgumentsException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String functionName;
|
||||
private Cons argumentList;
|
||||
|
||||
public TooManyArgumentsException(String functionName, Cons argumentList) {
|
||||
this.functionName = functionName;
|
||||
this.argumentList = argumentList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return format("too many arguments given to {0}: {1}", functionName, argumentList);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DottedArgumentListException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String functionName;
|
||||
private Cons argumentList;
|
||||
|
||||
public DottedArgumentListException(String functionName, Cons argumentList) {
|
||||
this.functionName = functionName;
|
||||
this.argumentList = argumentList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return format("dotted argument list given to {0}: {1}", functionName, argumentList);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BadArgumentTypeException extends LispException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String functionName;
|
||||
private String argument;
|
||||
private Class<? extends SExpression> expectedType;
|
||||
|
||||
public BadArgumentTypeException(String functionName, SExpression argument,
|
||||
Class<? extends SExpression> expectedType) {
|
||||
this.functionName = functionName;
|
||||
this.argument = argument.toString();
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return format("{0}: {1} is not the expected type of ''{2}''",
|
||||
functionName,
|
||||
argument,
|
||||
getExpectedTypeName());
|
||||
}
|
||||
|
||||
private String getExpectedTypeName() {
|
||||
DisplayName displayName = expectedType.getAnnotation(DisplayName.class);
|
||||
|
||||
return (displayName == null) ? "unknown" : displayName.value();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package function
|
||||
|
||||
import error.LispException
|
||||
import function.builtin.cons.LENGTH.getLength
|
||||
import sexpression.Cons
|
||||
import sexpression.DisplayName
|
||||
import sexpression.SExpression
|
||||
import java.math.BigInteger
|
||||
import java.text.MessageFormat.format
|
||||
|
||||
class ArgumentValidator(private val functionName: String) {
|
||||
|
||||
private var firstArgumentType: Class<out SExpression> = SExpression::class.java
|
||||
private var trailingArgumentType: Class<out SExpression> = SExpression::class.java
|
||||
private var excludedFirstArgumentType: Class<out SExpression>? = null
|
||||
private var excludedTrailingArgumentType: Class<out SExpression>? = null
|
||||
private var maximumNumberOfArguments: BigInteger? = null
|
||||
private var minimumNumberOfArguments: BigInteger? = null
|
||||
|
||||
fun setFirstArgumentExpectedType(argumentType: Class<out SExpression>) {
|
||||
this.firstArgumentType = argumentType
|
||||
}
|
||||
|
||||
fun setTrailingArgumentExpectedType(argumentType: Class<out SExpression>) {
|
||||
this.trailingArgumentType = argumentType
|
||||
}
|
||||
|
||||
fun setEveryArgumentExpectedType(argumentType: Class<out SExpression>) {
|
||||
this.firstArgumentType = argumentType
|
||||
this.trailingArgumentType = argumentType
|
||||
}
|
||||
|
||||
fun setFirstArgumentExcludedType(argumentType: Class<out SExpression>) {
|
||||
this.excludedFirstArgumentType = argumentType
|
||||
}
|
||||
|
||||
fun setTrailingArgumentExcludedType(argumentType: Class<out SExpression>) {
|
||||
this.excludedTrailingArgumentType = argumentType
|
||||
}
|
||||
|
||||
fun setEveryArgumentExcludedType(argumentType: Class<out SExpression>) {
|
||||
this.excludedFirstArgumentType = argumentType
|
||||
this.excludedTrailingArgumentType = argumentType
|
||||
}
|
||||
|
||||
fun setMaximumNumberOfArguments(maximumNumberOfArguments: Int) {
|
||||
this.maximumNumberOfArguments = BigInteger.valueOf(maximumNumberOfArguments.toLong())
|
||||
}
|
||||
|
||||
fun setMinimumNumberOfArguments(minimumNumberOfArguments: Int) {
|
||||
this.minimumNumberOfArguments = BigInteger.valueOf(minimumNumberOfArguments.toLong())
|
||||
}
|
||||
|
||||
fun setExactNumberOfArguments(exactNumberOfArguments: Int) {
|
||||
this.minimumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments.toLong())
|
||||
this.maximumNumberOfArguments = BigInteger.valueOf(exactNumberOfArguments.toLong())
|
||||
}
|
||||
|
||||
fun validate(argumentList: Cons) {
|
||||
validateListNotDotted(argumentList)
|
||||
validateListLength(argumentList)
|
||||
validateArgumentTypes(argumentList)
|
||||
}
|
||||
|
||||
private fun validateListNotDotted(argumentList: Cons) {
|
||||
var current = argumentList
|
||||
var next = current.rest
|
||||
|
||||
while (next.isCons) {
|
||||
current = next as Cons
|
||||
next = current.rest
|
||||
}
|
||||
|
||||
if (!next.isNull)
|
||||
throw DottedArgumentListException(functionName, argumentList)
|
||||
}
|
||||
|
||||
private fun validateListLength(argumentList: Cons) {
|
||||
if (containsTooFewArguments(argumentList))
|
||||
throw TooFewArgumentsException(functionName, argumentList)
|
||||
else if (containsTooManyArguments(argumentList))
|
||||
throw TooManyArgumentsException(functionName, argumentList)
|
||||
}
|
||||
|
||||
private fun containsTooFewArguments(argumentList: Cons) = isMinimum() && isLengthLessThanMinimum(argumentList)
|
||||
private fun isMinimum() = minimumNumberOfArguments != null
|
||||
private fun isLengthLessThanMinimum(argumentList: Cons) = getLength(argumentList) < minimumNumberOfArguments!!
|
||||
|
||||
private fun containsTooManyArguments(argumentList: Cons) = isMaximum() && isLengthGreaterThanMaximum(argumentList)
|
||||
private fun isMaximum() = maximumNumberOfArguments != null
|
||||
private fun isLengthGreaterThanMaximum(argumentList: Cons) = getLength(argumentList) > maximumNumberOfArguments!!
|
||||
|
||||
private fun validateArgumentTypes(argumentList: Cons) {
|
||||
validateFirstArgument(argumentList)
|
||||
validateTrailingArguments(argumentList)
|
||||
}
|
||||
|
||||
private fun validateFirstArgument(argumentList: Cons) {
|
||||
if (!isFirstArgumentValid(argumentList))
|
||||
throw BadArgumentTypeException(functionName, argumentList.first, firstArgumentType)
|
||||
}
|
||||
|
||||
private fun isFirstArgumentValid(argumentList: Cons) =
|
||||
argumentList.isNull || isExpectedFirstArgumentType(argumentList.first)
|
||||
|
||||
private fun isExpectedFirstArgumentType(firstArgument: SExpression) =
|
||||
firstArgumentType.isInstance(firstArgument) && !isExcludedFirstArgumentType(firstArgument)
|
||||
|
||||
private fun isExcludedFirstArgumentType(firstArgument: SExpression) =
|
||||
excludedFirstArgumentType != null && excludedFirstArgumentType!!.isInstance(firstArgument)
|
||||
|
||||
private fun validateTrailingArguments(argumentList: Cons) {
|
||||
var cons = argumentList.rest as Cons
|
||||
|
||||
while (!cons.isNull) {
|
||||
if (!isExpectedTrailingArgumentType(cons.first))
|
||||
throw BadArgumentTypeException(functionName, cons.first, trailingArgumentType)
|
||||
|
||||
cons = cons.rest as Cons
|
||||
}
|
||||
}
|
||||
|
||||
private fun isExpectedTrailingArgumentType(trailingArgument: SExpression) =
|
||||
trailingArgumentType.isInstance(trailingArgument) && !isExcludedTrailingArgumentType(trailingArgument)
|
||||
|
||||
private fun isExcludedTrailingArgumentType(trailingArgument: SExpression) =
|
||||
excludedTrailingArgumentType != null && excludedTrailingArgumentType!!.isInstance(trailingArgument)
|
||||
|
||||
class TooFewArgumentsException(functionName: String, argumentList: Cons) : LispException() {
|
||||
|
||||
override val message: String by lazy {
|
||||
format("too few arguments given to {0}: {1}", functionName, argumentList)
|
||||
}
|
||||
}
|
||||
|
||||
class TooManyArgumentsException(functionName: String, argumentList: Cons) : LispException() {
|
||||
|
||||
override val message: String by lazy {
|
||||
format("too many arguments given to {0}: {1}", functionName, argumentList)
|
||||
}
|
||||
}
|
||||
|
||||
class DottedArgumentListException(functionName: String, argumentList: Cons) : LispException() {
|
||||
|
||||
override val message: String by lazy {
|
||||
format("dotted argument list given to {0}: {1}", functionName, argumentList)
|
||||
}
|
||||
}
|
||||
|
||||
class BadArgumentTypeException(functionName: String,
|
||||
argument: SExpression,
|
||||
expectedType: Class<out SExpression>?) : LispException() {
|
||||
|
||||
private val expectedTypeName: String by lazy {
|
||||
val displayName = expectedType?.getAnnotation(DisplayName::class.java)
|
||||
|
||||
displayName?.value ?: "unknown"
|
||||
}
|
||||
|
||||
override val message: String by lazy {
|
||||
format("{0}: {1} is not the expected type of ''{2}''", functionName, argument.toString(), expectedTypeName)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue