package sexpression import recursion.MutualTailCall import recursion.MutualTailCalls.terminalValue import recursion.MutualTailCalls.recursiveCall @DisplayName("list") open class Cons(open var first: SExpression, open var rest: SExpression) : SExpression(), Iterable { override val isCons = true override fun toString(): String { return toStringTailRecursive(StringBuilder("(")).invoke() } private fun toStringTailRecursive(leadingString: StringBuilder): MutualTailCall { leadingString.append(first.toString()) if (rest.isNull) return terminalValue(leadingString.append(")").toString()) else if (rest.isCons) { return recursiveCall { (rest as Cons).toStringTailRecursive(leadingString.append(" ")) } } return terminalValue(leadingString.append(" . $rest)").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 } } }