diff --git a/src/main/kotlin/function/builtin/special/Case.kt b/src/main/kotlin/function/builtin/special/Case.kt index db65fa6..17809aa 100644 --- a/src/main/kotlin/function/builtin/special/Case.kt +++ b/src/main/kotlin/function/builtin/special/Case.kt @@ -8,7 +8,7 @@ import function.builtin.predicate.EQUAL.isEqual import sexpression.Cons import sexpression.Nil import sexpression.SExpression -import sexpression.Symbol +import sexpression.Symbol.Companion.T @FunctionNames("CASE") class Case(name: String) : LispSpecialFunction() { @@ -35,38 +35,27 @@ class Case(name: String) : LispSpecialFunction() { val keyList = clause.first return if (isMatch(key, keyList)) - evaluateConsequents(clause.rest) + evaluateConsequents(clause) else callTailRecursive(key, remainingClauses) } private fun isMatch(key: SExpression, keyList: SExpression) = when { keyList.isNull -> false - keyList.isCons -> containsMatch(key, keyList) - else -> isEqual(key, keyList) || isEqual(Symbol.T, keyList) + keyList.isCons -> containsMatch(key, keyList as Cons) + else -> isEqual(key, keyList) || isEqual(T, keyList) } - private fun containsMatch(key: SExpression, keyList: SExpression): Boolean { - if (keyList.isCons) { - (keyList as Cons).forEach { - if (isEqual(key, it.first)) { - return true - } + private fun containsMatch(key: SExpression, keyList: Cons): Boolean { + keyList.forEach { + if (isEqual(key, it.first)) { + return true } } return false } - private fun evaluateConsequents(consequentList: SExpression): SExpression { - var lastConsequentValue: SExpression = Nil - - if (consequentList.isCons) { - (consequentList as Cons).forEach { - lastConsequentValue = eval(it.first) - } - } - - return lastConsequentValue - } + private fun evaluateConsequents(clause: Cons) = + clause.drop(1).fold(Nil as SExpression) { _, it -> eval(it.first) } } diff --git a/src/test/kotlin/function/builtin/special/CaseTest.kt b/src/test/kotlin/function/builtin/special/CaseTest.kt index df7da51..5dca1c3 100644 --- a/src/test/kotlin/function/builtin/special/CaseTest.kt +++ b/src/test/kotlin/function/builtin/special/CaseTest.kt @@ -203,4 +203,11 @@ class CaseTest : SymbolAndFunctionCleaner() { evaluateString("(case :a nil)") } } + + @Test + fun caseWithDottedClause() { + val input = "(eval `(case :a ,(cons :a 'banana)))" + + assertSExpressionsMatch(parseString("nil"), evaluateString(input)) + } }