diff --git a/src/main/kotlin/function/ArgumentValidator.kt b/src/main/kotlin/function/ArgumentValidator.kt index c22dcce..35cc2ed 100644 --- a/src/main/kotlin/function/ArgumentValidator.kt +++ b/src/main/kotlin/function/ArgumentValidator.kt @@ -63,18 +63,12 @@ class ArgumentValidator(private val functionName: String) { } 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) + if (isArgumentListDotted(argumentList)) throw DottedArgumentListException(functionName, argumentList) } + private fun isArgumentListDotted(argumentList: Cons) = argumentList.isCons && !argumentList.last().rest.isNull + private fun validateListLength(argumentList: Cons) { if (containsTooFewArguments(argumentList)) throw TooFewArgumentsException(functionName, argumentList) @@ -110,13 +104,11 @@ class ArgumentValidator(private val functionName: String) { excludedFirstArgumentType != null && excludedFirstArgumentType!!.isInstance(firstArgument) private fun validateTrailingArguments(argumentList: Cons) { - var cons = argumentList.rest as Cons + val cons = argumentList.rest as Cons - while (!cons.isNull) { - if (!isExpectedTrailingArgumentType(cons.first)) - throw BadArgumentTypeException(functionName, cons.first, trailingArgumentType) - - cons = cons.rest as Cons + cons.forEach { + if (!isExpectedTrailingArgumentType(it.first)) + throw BadArgumentTypeException(functionName, it.first, trailingArgumentType) } } diff --git a/src/main/kotlin/sexpression/AtSignExpression.kt b/src/main/kotlin/sexpression/AtSignExpression.kt index 7f420e9..9ba271e 100644 --- a/src/main/kotlin/sexpression/AtSignExpression.kt +++ b/src/main/kotlin/sexpression/AtSignExpression.kt @@ -2,8 +2,7 @@ package sexpression class AtSignExpression(val expression: SExpression) : SExpression() { - override val isAtSign: Boolean - get() = true + override val isAtSign = true override fun toString() = "@$expression" } diff --git a/src/main/kotlin/sexpression/Atom.kt b/src/main/kotlin/sexpression/Atom.kt index 2cd3917..b87820a 100644 --- a/src/main/kotlin/sexpression/Atom.kt +++ b/src/main/kotlin/sexpression/Atom.kt @@ -3,8 +3,7 @@ package sexpression @DisplayName("atom") abstract class Atom(private val text: String) : SExpression() { - override val isAtom: Boolean - get() = true + override val isAtom = true override fun toString() = text } diff --git a/src/main/kotlin/sexpression/BackquoteExpression.kt b/src/main/kotlin/sexpression/BackquoteExpression.kt index 4dbe500..d205f96 100644 --- a/src/main/kotlin/sexpression/BackquoteExpression.kt +++ b/src/main/kotlin/sexpression/BackquoteExpression.kt @@ -2,8 +2,7 @@ package sexpression class BackquoteExpression(val expression: SExpression) : SExpression() { - override val isBackquote: Boolean - get() = true + override val isBackquote = true override fun toString() = "`$expression" } diff --git a/src/main/kotlin/sexpression/CommaExpression.kt b/src/main/kotlin/sexpression/CommaExpression.kt index ca93423..f35429b 100644 --- a/src/main/kotlin/sexpression/CommaExpression.kt +++ b/src/main/kotlin/sexpression/CommaExpression.kt @@ -2,8 +2,7 @@ package sexpression class CommaExpression(val expression: SExpression) : SExpression() { - override val isComma: Boolean - get() = true + override val isComma = true override fun toString() = ",$expression" } diff --git a/src/main/kotlin/sexpression/Cons.kt b/src/main/kotlin/sexpression/Cons.kt index d0972ac..a0b06a2 100644 --- a/src/main/kotlin/sexpression/Cons.kt +++ b/src/main/kotlin/sexpression/Cons.kt @@ -6,10 +6,9 @@ import recursion.TailCalls.done import recursion.TailCalls.tailCall @DisplayName("list") -open class Cons(open var first: SExpression, open var rest: SExpression) : SExpression() { +open class Cons(open var first: SExpression, open var rest: SExpression) : SExpression(), Iterable { - override val isCons: Boolean - get() = true + override val isCons = true override fun toString(): String { return toStringTailRecursive(StringBuilder("(")).invoke() @@ -26,4 +25,14 @@ open class Cons(open var first: SExpression, open var rest: SExpression) : SExpr return done(leadingString.append(" . " + rest.toString() + ")").toString()) } + + override fun iterator(): Iterator = ConsIterator(this) + + private class ConsIterator(start: Cons) : Iterator { + + private var current: SExpression = start + + override fun hasNext() = current.isCons + override fun next() = (current as Cons).apply { current = rest } + } } diff --git a/src/main/kotlin/sexpression/LambdaExpression.kt b/src/main/kotlin/sexpression/LambdaExpression.kt index 1138fec..2c4fe70 100644 --- a/src/main/kotlin/sexpression/LambdaExpression.kt +++ b/src/main/kotlin/sexpression/LambdaExpression.kt @@ -5,8 +5,7 @@ import function.UserDefinedFunction @DisplayName("lambda-expression") class LambdaExpression(val lambdaExpression: Cons, val function: UserDefinedFunction) : SExpression() { - override val isFunction: Boolean - get() = true + override val isFunction = true override fun toString() = lambdaExpression.toString() } diff --git a/src/main/kotlin/sexpression/LispNumber.kt b/src/main/kotlin/sexpression/LispNumber.kt index ea4cc1b..b961e2d 100644 --- a/src/main/kotlin/sexpression/LispNumber.kt +++ b/src/main/kotlin/sexpression/LispNumber.kt @@ -12,8 +12,7 @@ class LispNumber : Atom { var value: BigInteger? = null private set - override val isNumber: Boolean - get() = true + override val isNumber = true constructor(text: String) : super(text.replaceFirst("^0+(?!$)".toRegex(), "")) { try { @@ -27,7 +26,7 @@ class LispNumber : Atom { this.value = value } - inner class InvalidNumberException(private val text: String) : LispException() { + class InvalidNumberException(private val text: String) : LispException() { override val message: String get() = format("{0} is not a valid integer", text) } diff --git a/src/main/kotlin/sexpression/LispString.kt b/src/main/kotlin/sexpression/LispString.kt index fc1f8cb..17dd0d1 100644 --- a/src/main/kotlin/sexpression/LispString.kt +++ b/src/main/kotlin/sexpression/LispString.kt @@ -3,6 +3,5 @@ package sexpression @DisplayName("string") class LispString(text: String) : Atom(text) { - override val isString: Boolean - get() = true + override val isString = true } diff --git a/src/main/kotlin/sexpression/Nil.kt b/src/main/kotlin/sexpression/Nil.kt index 705b290..95f91f0 100644 --- a/src/main/kotlin/sexpression/Nil.kt +++ b/src/main/kotlin/sexpression/Nil.kt @@ -11,17 +11,10 @@ object Nil : Cons(T, T) { override var rest: SExpression = this set(_) {} - override val isNull: Boolean - get() = true - - override val isAtom: Boolean - get() = true - - override val isCons: Boolean - get() = false - - override val isSymbol: Boolean - get() = true + override val isNull = true + override val isAtom = true + override val isCons = false + override val isSymbol = true override fun toString() = "NIL" } diff --git a/src/main/kotlin/sexpression/SExpression.kt b/src/main/kotlin/sexpression/SExpression.kt index dcdf92c..bcc345e 100644 --- a/src/main/kotlin/sexpression/SExpression.kt +++ b/src/main/kotlin/sexpression/SExpression.kt @@ -3,7 +3,7 @@ package sexpression @DisplayName("s-expression") abstract class SExpression { - open val isNull: Boolean + open val isNull get() = false open val isAtom: Boolean diff --git a/src/main/kotlin/sexpression/Symbol.kt b/src/main/kotlin/sexpression/Symbol.kt index b5eeca7..d2801b5 100644 --- a/src/main/kotlin/sexpression/Symbol.kt +++ b/src/main/kotlin/sexpression/Symbol.kt @@ -5,8 +5,7 @@ import java.util.Locale @DisplayName("symbol") open class Symbol(text: String) : Atom(text.toUpperCase(Locale.ROOT)) { - override val isSymbol: Boolean - get() = true + override val isSymbol = true companion object { val T = Symbol("T")