mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
language: implement proper virtual machine support
This commit is contained in:
@ -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
|
||||
}
|
||||
}
|
||||
|
19
vm/src/main/kotlin/gay/pizza/pork/vm/StackFrame.kt
Normal file
19
vm/src/main/kotlin/gay/pizza/pork/vm/StackFrame.kt
Normal 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})"
|
||||
}
|
@ -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) ?:
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user