diff options
Diffstat (limited to 'src/LispData.kt')
-rw-r--r-- | src/LispData.kt | 24 |
1 files changed, 17 insertions, 7 deletions
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) } } |