From 0b518030fcdffb68e6b62ffddfe4b784db9f272c Mon Sep 17 00:00:00 2001 From: nea Date: Wed, 9 Aug 2023 20:06:15 +0200 Subject: Add rest arguments --- src/CoreBindings.kt | 26 +++++++++++++++----------- src/LispData.kt | 24 +++++++++++++++++------- test/res/test.lisp | 4 ++++ 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 -> "" + 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 -> ""} ${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 -> "" - LispData.LispNil -> "nil" - is LispData.LispNode -> resolved.node.toSource() - is LispData.LispString -> resolved.string - is LispData.LispNumber -> resolved.value.toString() - is LispData.LispInterpretedCallable -> ""} ${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() sealed class LispExecutable() : LispData() { abstract fun execute( executionContext: LispExecutionContext, @@ -30,17 +31,26 @@ sealed class LispData { stackFrame: StackFrame, args: List ): 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)) -- cgit