Handle dotted Case clause
This commit is contained in:
parent
9998a88569
commit
5d1606571a
|
@ -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 {
|
||||
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) }
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue