64 lines
1.7 KiB
Kotlin
64 lines
1.7 KiB
Kotlin
package function.builtin.cons
|
|
|
|
import function.ArgumentValidator
|
|
import function.FunctionNames
|
|
import function.LispFunction
|
|
import sexpression.Cons
|
|
import sexpression.Nil
|
|
import table.FunctionTable.lookupFunction
|
|
|
|
@FunctionNames("APPEND")
|
|
class Append(name: String) : LispFunction() {
|
|
|
|
private val argumentValidator = ArgumentValidator(name).apply {
|
|
setExactNumberOfArguments(2)
|
|
setEveryArgumentExpectedType(Cons::class.java)
|
|
}
|
|
|
|
private val firstListValidator = ArgumentValidator("$name|first-list|")
|
|
|
|
override fun call(argumentList: Cons): Cons {
|
|
argumentValidator.validate(argumentList)
|
|
|
|
val rest = argumentList.rest as Cons
|
|
val firstList = argumentList.first as Cons
|
|
val secondList = rest.first as Cons
|
|
|
|
return appendLists(firstList, secondList)
|
|
}
|
|
|
|
private fun appendLists(firstList: Cons, secondList: Cons): Cons {
|
|
firstListValidator.validate(firstList)
|
|
|
|
if (firstList.isNull)
|
|
return secondList
|
|
|
|
val appendedLists = copy(firstList)
|
|
appendedLists.last().rest = secondList
|
|
|
|
return appendedLists
|
|
}
|
|
|
|
private fun copy(list: Cons): Cons {
|
|
val newList = Cons(list.first, Nil)
|
|
var builder = newList
|
|
|
|
list.asSequence().drop(1).forEach {
|
|
builder.rest = Cons(it.first, Nil)
|
|
builder = builder.rest as Cons
|
|
}
|
|
|
|
return newList
|
|
}
|
|
|
|
companion object {
|
|
|
|
@JvmStatic
|
|
fun append(firstList: Cons, secondList: Cons): Cons {
|
|
return lookupAppend().appendLists(firstList, secondList)
|
|
}
|
|
|
|
private fun lookupAppend() = lookupFunction("APPEND") as Append
|
|
}
|
|
}
|