summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornea <nea@nea.moe>2023-08-09 20:06:15 +0200
committernea <nea@nea.moe>2023-08-09 20:06:15 +0200
commit0b518030fcdffb68e6b62ffddfe4b784db9f272c (patch)
treea4dbed21824703010e7f2d28008b1d8bdbb1cfe9
parentfc3911c68a4a8a0ff916b858e5fe029ed2ebe493 (diff)
downloadnealisp-0b518030fcdffb68e6b62ffddfe4b784db9f272c.tar.gz
nealisp-0b518030fcdffb68e6b62ffddfe4b784db9f272c.tar.bz2
nealisp-0b518030fcdffb68e6b62ffddfe4b784db9f272c.zip
Add rest arguments
-rw-r--r--src/CoreBindings.kt26
-rw-r--r--src/LispData.kt24
-rw-r--r--test/res/test.lisp4
3 files changed, 36 insertions, 18 deletions
diff --git a/src/CoreBindings.kt b/src/CoreBindings.kt
index 645a4ae..aa40366 100644
--- a/src/CoreBindings.kt
+++ b/src/CoreBindings.kt
@@ -83,18 +83,22 @@ object CoreBindings {
lastResult ?: context.reportError("Seq cannot be invoked with 0 argumens", callsite)
}
+ private fun stringify(thing: LispData): String {
+ return when (thing) {
+ is LispData.Atom -> ":${thing.label}"
+ is LispData.JavaExecutable -> "<native code>"
+ LispData.LispNil -> "nil"
+ is LispData.LispNode -> thing.node.toSource()
+ is LispData.LispList -> thing.elements.joinToString(", ", "[", "]") { stringify(it) }
+ is LispData.LispString -> thing.string
+ is LispData.LispNumber -> thing.value.toString()
+ is LispData.LispInterpretedCallable -> "<function ${thing.name ?: "<anonymous>"} ${thing.argNames} ${thing.body.toSource()}>"
+ }
+
+ }
+
val debuglog = LispData.externalRawCall { context, callsite, stackFrame, args ->
- println(args.joinToString(" ") { arg ->
- when (val resolved = context.resolveValue(stackFrame, arg)) {
- is LispData.Atom -> ":${resolved.label}"
- is LispData.JavaExecutable -> "<native code>"
- LispData.LispNil -> "nil"
- is LispData.LispNode -> resolved.node.toSource()
- is LispData.LispString -> resolved.string
- is LispData.LispNumber -> resolved.value.toString()
- is LispData.LispInterpretedCallable -> "<function ${resolved.name ?: "<anonymous>"} ${resolved.argNames} ${resolved.body.toSource()}>"
- }
- })
+ println(args.joinToString(" ") { stringify(context.resolveValue(stackFrame, it)) })
LispData.LispNil
}
val add = LispData.externalCall { args, reportError ->
diff --git a/src/LispData.kt b/src/LispData.kt
index 11a2451..1745762 100644
--- a/src/LispData.kt
+++ b/src/LispData.kt
@@ -7,6 +7,7 @@ sealed class LispData {
data class LispString(val string: String) : LispData()
data class LispNumber(val value: Double) : LispData()
data class LispNode(val node: LispAst.LispNode) : LispData()
+ class LispList(val elements: List<LispData>) : LispData()
sealed class LispExecutable() : LispData() {
abstract fun execute(
executionContext: LispExecutionContext,
@@ -30,17 +31,26 @@ sealed class LispData {
stackFrame: StackFrame,
args: List<LispAst.LispNode>
): LispData {
- if (argNames.size != args.size) {
+
+ val invocationFrame = declarationStackFrame.fork()
+ if (argNames.lastOrNull() == "...") {
+ for ((name, value) in argNames.dropLast(1).zip(args)) {
+ invocationFrame.setValueLocal(name, executionContext.resolveValue(stackFrame, value))
+ }
+ invocationFrame.setValueLocal(
+ "...",
+ LispList(
+ args.drop(argNames.size - 1).map { executionContext.resolveValue(stackFrame, it) })
+ )
+ } else if (argNames.size != args.size) {
return executionContext.reportError(
"Expected ${argNames.size} arguments, got ${args.size} instead",
callsite
)
- }
- val invocationFrame = declarationStackFrame.fork()
-
- for ((name, value) in argNames.zip(args)) {
- invocationFrame.setValueLocal(name, executionContext.resolveValue(stackFrame, value))
- }
+ } else
+ for ((name, value) in argNames.zip(args)) {
+ invocationFrame.setValueLocal(name, executionContext.resolveValue(stackFrame, value))
+ }
return executionContext.executeLisp(invocationFrame, body)
}
}
diff --git a/test/res/test.lisp b/test/res/test.lisp
index cc20808..79c96dc 100644
--- a/test/res/test.lisp
+++ b/test/res/test.lisp
@@ -3,6 +3,10 @@
(myfun :myfunworks)
((lambda (a) (debuglog a)) :atom)
(debuglog a)
+(defun testlog (a ...) (seq
+ (debuglog "a" a)
+ (debuglog "..." ...)))
+(testlog :test :work :whatever)
(def helloworld (pure "hello world"))
(debuglog helloworld (helloworld))
(debuglog "+" (+ 1.2 15))