Standardize cons iteration
This commit is contained in:
parent
3f82b473b4
commit
065d2136ed
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,5 @@ package sexpression
|
|||
@DisplayName("string")
|
||||
class LispString(text: String) : Atom(text) {
|
||||
|
||||
override val isString: Boolean
|
||||
get() = true
|
||||
override val isString = true
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue