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.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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue