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) {
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)
}
}

View File

@ -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"
}

View File

@ -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
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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<Cons> {
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<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")
class LambdaExpression(val lambdaExpression: Cons, val function: UserDefinedFunction) : SExpression() {
override val isFunction: Boolean
get() = true
override val isFunction = true
override fun toString() = lambdaExpression.toString()
}

View File

@ -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)
}

View File

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

View File

@ -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"
}

View File

@ -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

View File

@ -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")