summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/builtins.lisp10
-rw-r--r--res/stdtest.lisp6
-rw-r--r--src/CoreBindings.kt29
-rw-r--r--src/LispData.kt8
-rw-r--r--test/res/test.lisp10
5 files changed, 56 insertions, 7 deletions
diff --git a/res/builtins.lisp b/res/builtins.lisp
index e355c2f..1564e62 100644
--- a/res/builtins.lisp
+++ b/res/builtins.lisp
@@ -20,3 +20,13 @@
(def false :false)
(export true false)
+(comment "boolean operations. all of those are strict")
+(defun | (l r) (if l true r))
+(defun & (l r) (if l r false))
+(defun not (v) (if v false true))
+(defun ^ (l r) (if l (not r) r))
+(export | & not ^)
+
+(comment "comparisons")
+(defun gt (l r) (lt r l))
+(export gt)
diff --git a/res/stdtest.lisp b/res/stdtest.lisp
index 8de5164..bf230b3 100644
--- a/res/stdtest.lisp
+++ b/res/stdtest.lisp
@@ -14,3 +14,9 @@
(defun test.assert (cond message) (if cond noop (ntest.fail message)))
(export test.assert)
+(comment "Assert that two arguments are equal. Returns a closure")
+(defun test.assert-eq (actual expected)
+ (test.assert
+ (= actual expected)
+ (tostring "Expected" expected "got" actual)))
+(export test.assert-eq)
diff --git a/src/CoreBindings.kt b/src/CoreBindings.kt
index 571b499..d88c950 100644
--- a/src/CoreBindings.kt
+++ b/src/CoreBindings.kt
@@ -147,9 +147,8 @@ object CoreBindings {
?: return@externalCall reportError("Unexpected argument $it, expected number")
).value
}
- LispData.LispNumber(args.drop(1).fold(c.first()) { a, b ->
- a - (b as? LispData.LispNumber
- ?: return@externalCall reportError("Unexpected argument $b, expected number")).value
+ LispData.LispNumber(c.drop(1).fold(c.first()) { a, b ->
+ a - b
})
}
val mul = LispData.externalCall("mul") { args, reportError ->
@@ -161,6 +160,12 @@ object CoreBindings {
?: return@externalCall reportError("Unexpected argument $b, expected number")).value
})
}
+ val eq = LispData.externalCall("eq") { args, reportError ->
+ if (args.size == 0) {
+ return@externalCall reportError("Cannot call eq without at least 1 argument")
+ }
+ LispData.boolean(!args.zipWithNext().any { it.first != it.second })
+ }
val div = LispData.externalCall("div") { args, reportError ->
if (args.size == 0) {
return@externalCall reportError("Cannot call div without at least 1 argument")
@@ -170,11 +175,21 @@ object CoreBindings {
?: return@externalCall reportError("Unexpected argument $it, expected number")
).value
}
- LispData.LispNumber(args.drop(1).fold(c.first()) { a, b ->
- a / (b as? LispData.LispNumber
- ?: return@externalCall reportError("Unexpected argument $b, expected number")).value
+ LispData.LispNumber(c.drop(1).fold(c.first()) { a, b ->
+ a / b
})
}
+ val less = LispData.externalCall("less") { args, reportError ->
+ if (args.size != 2) {
+ return@externalCall reportError("Cannot call less without exactly 2 arguments")
+ }
+ val (left, right) = args.map {
+ (it as? LispData.LispNumber
+ ?: return@externalCall reportError("Unexpected argument $it, expected number")
+ ).value
+ }
+ LispData.boolean(left < right)
+ }
val import = LispData.externalRawCall("import") { context, callsite, stackFrame, args ->
if (args.size != 1) {
return@externalRawCall context.reportError("import needs at least one argument", callsite)
@@ -194,6 +209,8 @@ object CoreBindings {
bindings.setValueLocal("/", div)
bindings.setValueLocal("*", mul)
bindings.setValueLocal("-", sub)
+ bindings.setValueLocal("lt", less)
+ bindings.setValueLocal("=", eq)
}
fun offerAllTo(bindings: StackFrame) {
diff --git a/src/LispData.kt b/src/LispData.kt
index 5af3dd4..8eac3f7 100644
--- a/src/LispData.kt
+++ b/src/LispData.kt
@@ -99,5 +99,13 @@ sealed class LispData {
): LispExecutable {
return LispInterpretedCallable(declarationStackFrame, args, body, nameHint)
}
+
+ fun boolean(b: Boolean): Atom {
+ return if (b) {
+ CoreBindings.trueValue
+ } else {
+ CoreBindings.falseValue
+ }
+ }
}
}
diff --git a/test/res/test.lisp b/test/res/test.lisp
index eea180c..79d259d 100644
--- a/test/res/test.lisp
+++ b/test/res/test.lisp
@@ -28,6 +28,14 @@
(test.test "Funny test" (seq
(debuglog "Funny test running")
((test.assert false "False failed"))
+ ((test.assert-eq "funny" "unfunny"))
((test.fail "Test failed"))))
-
+(test.test "Test equality" (seq
+ ((test.assert-eq false false))
+ ((test.assert-eq (not false) true))
+ ((test.assert-eq (not true) false))
+ ((test.assert-eq (& true true) true))
+ ((test.assert-eq (& true false) false))
+ ((test.assert-eq (& false true) false))
+ ((test.assert-eq (& false false) false))))