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
|
package moe.nea.lisp
class LispExecutionContext() {
private val errorReporter = LispErrorReporter()
private val rootStackFrame = StackFrame(null)
fun reportError(name: String, position: HasLispPosition): LispData.LispNil {
println("Error: $name ${position.position}")
return LispData.LispNil
}
fun genBindings(): StackFrame {
return StackFrame(rootStackFrame)
}
fun executeProgram(stackFrame: StackFrame, program: LispAst.Program) {
for (node in program.nodes) {
executeLisp(stackFrame, node)
}
}
fun executeLisp(stackFrame: StackFrame, node: LispAst.LispNode): LispData {
when (node) {
is LispAst.Parenthesis -> {
val first = node.items.firstOrNull()
?: return reportError("Cannot execute empty parenthesis ()", node)
val rest = node.items.drop(1)
return when (val resolvedValue = resolveValue(stackFrame, first)) {
is LispData.LispExecutable -> {
resolvedValue.execute(this, node, stackFrame, rest)
}
else -> reportError("Cannot evaluate expression of type $resolvedValue", node)
}
}
else -> return reportError("Expected invocation", node)
}
}
fun resolveValue(stackFrame: StackFrame, node: LispAst.LispNode): LispData {
return when (node) {
is LispAst.Atom -> LispData.Atom(node.label)
is LispAst.Parenthesis -> executeLisp(stackFrame, node)
is LispAst.Reference -> stackFrame.resolveReference(node.label)
?: reportError("Could not resolve variable ${node.label}", node)
is LispAst.NumberLiteral -> LispData.LispNumber(node.numberValue)
is LispAst.StringLiteral -> LispData.LispString(node.parsedString)
}
}
}
|