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.Cons
import sexpression.Nil import sexpression.Nil
import sexpression.SExpression import sexpression.SExpression
import sexpression.Symbol import sexpression.Symbol.Companion.T
@FunctionNames("CASE") @FunctionNames("CASE")
class Case(name: String) : LispSpecialFunction() { class Case(name: String) : LispSpecialFunction() {
@ -35,38 +35,27 @@ class Case(name: String) : LispSpecialFunction() {
val keyList = clause.first val keyList = clause.first
return if (isMatch(key, keyList)) return if (isMatch(key, keyList))
evaluateConsequents(clause.rest) evaluateConsequents(clause)
else else
callTailRecursive(key, remainingClauses) callTailRecursive(key, remainingClauses)
} }
private fun isMatch(key: SExpression, keyList: SExpression) = when { private fun isMatch(key: SExpression, keyList: SExpression) = when {
keyList.isNull -> false keyList.isNull -> false
keyList.isCons -> containsMatch(key, keyList) keyList.isCons -> containsMatch(key, keyList as Cons)
else -> isEqual(key, keyList) || isEqual(Symbol.T, keyList) else -> isEqual(key, keyList) || isEqual(T, keyList)
} }
private fun containsMatch(key: SExpression, keyList: SExpression): Boolean { private fun containsMatch(key: SExpression, keyList: Cons): Boolean {
if (keyList.isCons) { keyList.forEach {
(keyList as Cons).forEach {
if (isEqual(key, it.first)) { if (isEqual(key, it.first)) {
return true return true
} }
} }
}
return false return false
} }
private fun evaluateConsequents(consequentList: SExpression): SExpression { private fun evaluateConsequents(clause: Cons) =
var lastConsequentValue: SExpression = Nil clause.drop(1).fold(Nil as SExpression) { _, it -> eval(it.first) }
if (consequentList.isCons) {
(consequentList as Cons).forEach {
lastConsequentValue = eval(it.first)
}
}
return lastConsequentValue
}
} }

View File

@ -203,4 +203,11 @@ class CaseTest : SymbolAndFunctionCleaner() {
evaluateString("(case :a nil)") evaluateString("(case :a nil)")
} }
} }
@Test
fun caseWithDottedClause() {
val input = "(eval `(case :a ,(cons :a 'banana)))"
assertSExpressionsMatch(parseString("nil"), evaluateString(input))
}
} }