diff options
-rw-r--r-- | res/builtins.lisp | 10 | ||||
-rw-r--r-- | res/stdtest.lisp | 6 | ||||
-rw-r--r-- | src/CoreBindings.kt | 29 | ||||
-rw-r--r-- | src/LispData.kt | 8 | ||||
-rw-r--r-- | test/res/test.lisp | 10 |
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)))) |