1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
package moe.nea.lisp
sealed class LispData {
fun <T : Any> lispCastObject(lClass: LispClass<T>): LispObject<T>? {
if (this !is LispObject<*>) return null
if (this.handler != lClass) return null
return this as LispObject<T>
}
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<T : Any>(val data: T, val handler: LispClass<T>) : LispData()
sealed class LispExecutable() : LispData() {
abstract fun execute(
executionContext: LispExecutionContext,
callsite: LispAst.LispNode,
stackFrame: StackFrame,
args: List<LispAst.LispNode>
): LispData
}
abstract class JavaExecutable : LispExecutable() {
}
data class LispInterpretedCallable(
val declarationStackFrame: StackFrame,
val argNames: List<String>,
val body: LispAst.Parenthesis,
val name: String?,
) : LispExecutable() {
override fun execute(
executionContext: LispExecutionContext,
callsite: LispAst.LispNode,
stackFrame: StackFrame,
args: List<LispAst.LispNode>
): 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<T : Any> {
fun access(obj: T, name: String): LispData
fun instantiate(obj: T) = LispObject(obj, this)
}
object LispStringClass : LispClass<String> {
override fun access(obj: String, name: String): LispData {
return LispNil
}
}
companion object {
fun string(value: String): LispObject<String> =
LispStringClass.instantiate(value)
fun externalRawCall(callable: (context: LispExecutionContext, callsite: LispAst.LispNode, stackFrame: StackFrame, args: List<LispAst.LispNode>) -> LispData): LispExecutable {
return object : JavaExecutable() {
override fun execute(
executionContext: LispExecutionContext,
callsite: LispAst.LispNode,
stackFrame: StackFrame,
args: List<LispAst.LispNode>
): LispData {
return callable.invoke(executionContext, callsite, stackFrame, args)
}
}
}
fun externalCall(callable: (args: List<LispData>, reportError: (String) -> LispData) -> LispData): LispExecutable {
return object : JavaExecutable() {
override fun execute(
executionContext: LispExecutionContext,
callsite: LispAst.LispNode,
stackFrame: StackFrame,
args: List<LispAst.LispNode>
): LispData {
val mappedArgs = args.map { executionContext.resolveValue(stackFrame, it) }
return callable.invoke(mappedArgs) { executionContext.reportError(it, callsite) }
}
}
}
fun createLambda(
declarationStackFrame: StackFrame,
args: List<String>,
body: LispAst.Parenthesis,
nameHint: String? = null,
): LispExecutable {
return LispInterpretedCallable(declarationStackFrame, args, body, nameHint)
}
}
}
|