language: implement proper virtual machine support

This commit is contained in:
2023-11-28 05:23:48 -08:00
parent 8951c3cd60
commit f2ff23e9be
55 changed files with 312 additions and 63 deletions

View File

@ -47,11 +47,14 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
}
}
fun loadLocal(id: UInt) {
fun localAt(id: UInt): Any {
val localSet = locals.last()
val local = localSet[id]
?: throw VirtualMachineException("Attempted to load local $id but it was not stored.")
push(local)
return localSet[id] ?:
throw VirtualMachineException("Attempted to load local $id but it was not stored.")
}
fun loadLocal(id: UInt) {
push(localAt(id))
}
fun storeLocal(id: UInt) {
@ -108,4 +111,11 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
exitFlag = false
autoNextInst = true
}
fun frame(at: UInt = inst): StackFrame? {
val (symbolInfo, rel) = world.symbolTable.lookup(at) ?: (null to null)
return if (symbolInfo != null && rel != null) {
StackFrame(symbolInfo, rel)
} else null
}
}

View File

@ -0,0 +1,19 @@
package gay.pizza.pork.vm
import gay.pizza.pork.bytecode.CompiledWorld
import gay.pizza.pork.bytecode.Op
import gay.pizza.pork.bytecode.SymbolInfo
data class StackFrame(val symbolInfo: SymbolInfo, val rel: UInt) {
val worldCodeOffset: UInt
get() = symbolInfo.offset + rel
fun opInWorld(world: CompiledWorld): Op =
world.code[worldCodeOffset.toInt()]
fun describeInWorld(world: CompiledWorld): String =
"StackFrame(${worldCodeOffset}, ${symbolInfo.slab} ${symbolInfo.symbol} + ${rel}, ${opInWorld(world)})"
override fun toString(): String =
"StackFrame(${worldCodeOffset}, ${symbolInfo.slab} ${symbolInfo.symbol} + ${rel})"
}

View File

@ -10,7 +10,7 @@ import gay.pizza.pork.frontend.World
class VirtualMachineProvider(val world: World) : ExecutionContextProvider {
override fun prepare(importLocator: ImportLocator, entryPointSymbol: Symbol, nativeRegistry: NativeRegistry): ExecutionContext {
val compiler = Compiler()
val compiler = Compiler(world)
val slab = world.load(importLocator)
val compilableSlab = compiler.compilableSlabs.of(slab)
val compilableSymbol = compilableSlab.resolve(entryPointSymbol) ?:

View File

@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler
object AddOpHandler : OpHandler(Opcode.Add) {
override fun handle(machine: InternalMachine, op: Op) {
val left = machine.pop<Int>()
val right = machine.pop<Int>()
val left = machine.pop<Int>()
machine.push(left + right)
}
}

View File

@ -2,6 +2,7 @@ package gay.pizza.pork.vm.ops
import gay.pizza.pork.bytecode.Op
import gay.pizza.pork.bytecode.Opcode
import gay.pizza.pork.execution.None
import gay.pizza.pork.vm.InternalMachine
import gay.pizza.pork.vm.OpHandler
@ -9,9 +10,10 @@ object NativeOpHandler : OpHandler(Opcode.Native) {
override fun handle(machine: InternalMachine, op: Op) {
val argumentCount = op.args[2]
val arguments = mutableListOf<Any>()
for (i in 0u until argumentCount) {
machine.loadLocal(i)
arguments.add(machine.popAnyValue())
var x = argumentCount
while (x > 0u) {
x--
arguments.add(machine.localAt(x))
}
val formConstant = machine.world.constantPool.read(op.args[0])
val form = formConstant.readAsString()
@ -22,6 +24,7 @@ object NativeOpHandler : OpHandler(Opcode.Native) {
defs.add(machine.pop())
}
val function = provider.provideNativeFunction(defs)
function.invoke(arguments)
val result = function.invoke(arguments)
machine.push(if (result == Unit) None else result)
}
}

View File

@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler
object SubtractOpHandler : OpHandler(Opcode.Subtract) {
override fun handle(machine: InternalMachine, op: Op) {
val left = machine.pop<Int>()
val right = machine.pop<Int>()
val left = machine.pop<Int>()
machine.push(left - right)
}
}