Handle dotted Case clause

This commit is contained in:
Mike Cifelli 2018-10-28 09:02:21 -04:00
parent 9998a88569
commit 5d1606571a
2 changed files with 17 additions and 21 deletions

View File

@ -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) }
}

View File

@ -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))
}
}