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) {
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
Loading…
Reference in New Issue