From b530d6360308ac1f68cf2508fa5bd4a085a8bec0 Mon Sep 17 00:00:00 2001 From: nea Date: Wed, 9 Aug 2023 16:18:48 +0200 Subject: Initial commit --- src/LispData.kt | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/LispData.kt (limited to 'src/LispData.kt') diff --git a/src/LispData.kt b/src/LispData.kt new file mode 100644 index 0000000..1f13ad3 --- /dev/null +++ b/src/LispData.kt @@ -0,0 +1,105 @@ +package moe.nea.lisp + +sealed class LispData { + + fun lispCastObject(lClass: LispClass): LispObject? { + if (this !is LispObject<*>) return null + if (this.handler != lClass) return null + return this as LispObject + } + + object LispNil : LispData() + data class Atom(val label: String) : LispData() + data class LispNode(val node: LispAst.LispNode) : LispData() + data class LispNumber(val number: Double) : LispData() + data class LispObject(val data: T, val handler: LispClass) : LispData() + sealed class LispExecutable() : LispData() { + abstract fun execute( + executionContext: LispExecutionContext, + callsite: LispAst.LispNode, + stackFrame: StackFrame, + args: List + ): LispData + } + + + abstract class JavaExecutable : LispExecutable() { + } + + data class LispInterpretedCallable( + val declarationStackFrame: StackFrame, + val argNames: List, + val body: LispAst.Parenthesis, + val name: String?, + ) : LispExecutable() { + override fun execute( + executionContext: LispExecutionContext, + callsite: LispAst.LispNode, + stackFrame: StackFrame, + args: List + ): LispData { + if (argNames.size != args.size) { + TODO("ERROR") + } + val invocationFrame = declarationStackFrame.fork() + + for ((name, value) in argNames.zip(args)) { + invocationFrame.setValueLocal(name, executionContext.resolveValue(stackFrame, value)) + } + return executionContext.executeLisp(invocationFrame, body) + } + } + + interface LispClass { + fun access(obj: T, name: String): LispData + fun instantiate(obj: T) = LispObject(obj, this) + } + + object LispStringClass : LispClass { + override fun access(obj: String, name: String): LispData { + return LispNil + } + } + + companion object { + fun string(value: String): LispObject = + LispStringClass.instantiate(value) + + fun externalRawCall(callable: (context: LispExecutionContext, callsite: LispAst.LispNode, stackFrame: StackFrame, args: List) -> LispData): LispExecutable { + return object : JavaExecutable() { + override fun execute( + executionContext: LispExecutionContext, + callsite: LispAst.LispNode, + stackFrame: StackFrame, + args: List + ): LispData { + return callable.invoke(executionContext, callsite, stackFrame, args) + } + } + } + + fun externalCall(callable: (args: List, reportError: (String) -> LispData) -> LispData): LispExecutable { + return object : JavaExecutable() { + override fun execute( + executionContext: LispExecutionContext, + callsite: LispAst.LispNode, + stackFrame: StackFrame, + args: List + ): LispData { + val mappedArgs = args.map { executionContext.resolveValue(stackFrame, it) } + return callable.invoke(mappedArgs) { executionContext.reportError(it, callsite) } + } + } + } + + + fun createLambda( + declarationStackFrame: StackFrame, + args: List, + body: LispAst.Parenthesis, + nameHint: String? = null, + ): LispExecutable { + return LispInterpretedCallable(declarationStackFrame, args, body, nameHint) + } + } +} -- cgit