Standardize cons iteration

This commit is contained in:
Mike Cifelli 2018-09-16 13:03:01 -04:00
parent 3f82b473b4
commit 065d2136ed
12 changed files with 33 additions and 47 deletions

View File

@ -63,18 +63,12 @@ class ArgumentValidator(private val functionName: String) {
} }
private fun validateListNotDotted(argumentList: Cons) { private fun validateListNotDotted(argumentList: Cons) {
var current = argumentList if (isArgumentListDotted(argumentList))
var next = current.rest
while (next.isCons) {
current = next as Cons
next = current.rest
}
if (!next.isNull)
throw DottedArgumentListException(functionName, argumentList) throw DottedArgumentListException(functionName, argumentList)
} }
private fun isArgumentListDotted(argumentList: Cons) = argumentList.isCons && !argumentList.last().rest.isNull
private fun validateListLength(argumentList: Cons) { private fun validateListLength(argumentList: Cons) {
if (containsTooFewArguments(argumentList)) if (containsTooFewArguments(argumentList))
throw TooFewArgumentsException(functionName, argumentList) throw TooFewArgumentsException(functionName, argumentList)
@ -110,13 +104,11 @@ class ArgumentValidator(private val functionName: String) {
excludedFirstArgumentType != null && excludedFirstArgumentType!!.isInstance(firstArgument) excludedFirstArgumentType != null && excludedFirstArgumentType!!.isInstance(firstArgument)
private fun validateTrailingArguments(argumentList: Cons) { private fun validateTrailingArguments(argumentList: Cons) {
var cons = argumentList.rest as Cons val cons = argumentList.rest as Cons
while (!cons.isNull) { cons.forEach {
if (!isExpectedTrailingArgumentType(cons.first)) if (!isExpectedTrailingArgumentType(it.first))
throw BadArgumentTypeException(functionName, cons.first, trailingArgumentType) throw BadArgumentTypeException(functionName, it.first, trailingArgumentType)
cons = cons.rest as Cons
} }
} }

View File

@ -2,8 +2,7 @@ package sexpression
class AtSignExpression(val expression: SExpression) : SExpression() { class AtSignExpression(val expression: SExpression) : SExpression() {
override val isAtSign: Boolean override val isAtSign = true
get() = true
override fun toString() = "@$expression" override fun toString() = "@$expression"
} }

View File

@ -3,8 +3,7 @@ package sexpression
@DisplayName("atom") @DisplayName("atom")
abstract class Atom(private val text: String) : SExpression() { abstract class Atom(private val text: String) : SExpression() {
override val isAtom: Boolean override val isAtom = true
get() = true
override fun toString() = text override fun toString() = text
} }

View File

@ -2,8 +2,7 @@ package sexpression
class BackquoteExpression(val expression: SExpression) : SExpression() { class BackquoteExpression(val expression: SExpression) : SExpression() {
override val isBackquote: Boolean override val isBackquote = true
get() = true
override fun toString() = "`$expression" override fun toString() = "`$expression"
} }

View File

@ -2,8 +2,7 @@ package sexpression
class CommaExpression(val expression: SExpression) : SExpression() { class CommaExpression(val expression: SExpression) : SExpression() {
override val isComma: Boolean override val isComma = true
get() = true
override fun toString() = ",$expression" override fun toString() = ",$expression"
} }

View File

@ -6,10 +6,9 @@ import recursion.TailCalls.done
import recursion.TailCalls.tailCall import recursion.TailCalls.tailCall
@DisplayName("list") @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<Cons> {
override val isCons: Boolean override val isCons = true
get() = true
override fun toString(): String { override fun toString(): String {
return toStringTailRecursive(StringBuilder("(")).invoke() 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()) return done(leadingString.append(" . " + rest.toString() + ")").toString())
} }
override fun iterator(): Iterator<Cons> = ConsIterator(this)
private class ConsIterator(start: Cons) : Iterator<Cons> {
private var current: SExpression = start
override fun hasNext() = current.isCons
override fun next() = (current as Cons).apply { current = rest }
}
} }

View File

@ -5,8 +5,7 @@ import function.UserDefinedFunction
@DisplayName("lambda-expression") @DisplayName("lambda-expression")
class LambdaExpression(val lambdaExpression: Cons, val function: UserDefinedFunction) : SExpression() { class LambdaExpression(val lambdaExpression: Cons, val function: UserDefinedFunction) : SExpression() {
override val isFunction: Boolean override val isFunction = true
get() = true
override fun toString() = lambdaExpression.toString() override fun toString() = lambdaExpression.toString()
} }

View File

@ -12,8 +12,7 @@ class LispNumber : Atom {
var value: BigInteger? = null var value: BigInteger? = null
private set private set
override val isNumber: Boolean override val isNumber = true
get() = true
constructor(text: String) : super(text.replaceFirst("^0+(?!$)".toRegex(), "")) { constructor(text: String) : super(text.replaceFirst("^0+(?!$)".toRegex(), "")) {
try { try {
@ -27,7 +26,7 @@ class LispNumber : Atom {
this.value = value this.value = value
} }
inner class InvalidNumberException(private val text: String) : LispException() { class InvalidNumberException(private val text: String) : LispException() {
override val message: String override val message: String
get() = format("{0} is not a valid integer", text) get() = format("{0} is not a valid integer", text)
} }

View File

@ -3,6 +3,5 @@ package sexpression
@DisplayName("string") @DisplayName("string")
class LispString(text: String) : Atom(text) { class LispString(text: String) : Atom(text) {
override val isString: Boolean override val isString = true
get() = true
} }

View File

@ -11,17 +11,10 @@ object Nil : Cons(T, T) {
override var rest: SExpression = this override var rest: SExpression = this
set(_) {} set(_) {}
override val isNull: Boolean override val isNull = true
get() = true override val isAtom = true
override val isCons = false
override val isAtom: Boolean override val isSymbol = true
get() = true
override val isCons: Boolean
get() = false
override val isSymbol: Boolean
get() = true
override fun toString() = "NIL" override fun toString() = "NIL"
} }

View File

@ -3,7 +3,7 @@ package sexpression
@DisplayName("s-expression") @DisplayName("s-expression")
abstract class SExpression { abstract class SExpression {
open val isNull: Boolean open val isNull
get() = false get() = false
open val isAtom: Boolean open val isAtom: Boolean

View File

@ -5,8 +5,7 @@ import java.util.Locale
@DisplayName("symbol") @DisplayName("symbol")
open class Symbol(text: String) : Atom(text.toUpperCase(Locale.ROOT)) { open class Symbol(text: String) : Atom(text.toUpperCase(Locale.ROOT)) {
override val isSymbol: Boolean override val isSymbol = true
get() = true
companion object { companion object {
val T = Symbol("T") val T = Symbol("T")