diff --git a/tool/build.gradle.kts b/tool/build.gradle.kts index 9174b7c..29bddc7 100644 --- a/tool/build.gradle.kts +++ b/tool/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { api(project(":compiler")) api(project(":vm")) api("com.github.ajalt.clikt:clikt:4.2.0") + api("com.charleskorn.kaml:kaml:0.55.0") implementation(project(":common")) } diff --git a/tool/src/main/kotlin/gay/pizza/pork/tool/CompileCommand.kt b/tool/src/main/kotlin/gay/pizza/pork/tool/CompileCommand.kt index 4689698..1bb892e 100644 --- a/tool/src/main/kotlin/gay/pizza/pork/tool/CompileCommand.kt +++ b/tool/src/main/kotlin/gay/pizza/pork/tool/CompileCommand.kt @@ -1,5 +1,7 @@ package gay.pizza.pork.tool +import com.charleskorn.kaml.PolymorphismStyle +import com.charleskorn.kaml.Yaml import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.arguments.argument import gay.pizza.dough.fs.PlatformFsProvider @@ -8,10 +10,7 @@ import gay.pizza.pork.bir.IrWorld import gay.pizza.pork.bytecode.CompiledWorld import gay.pizza.pork.compiler.Compiler import gay.pizza.pork.minimal.FileTool -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.json.Json -@OptIn(ExperimentalSerializationApi::class) class CompileCommand : CliktCommand(help = "Compile Pork to Bytecode", name = "compile") { val path by argument("file") @@ -30,11 +29,10 @@ class CompileCommand : CliktCommand(help = "Compile Pork to Bytecode", name = "c } private fun printCompiledIr(irWorld: IrWorld) { - val json = Json { - prettyPrint = true - prettyPrintIndent = " " - } - println(json.encodeToString(IrWorld.serializer(), irWorld)) + val yaml = Yaml(configuration = Yaml.default.configuration.copy( + polymorphismStyle = PolymorphismStyle.Property + )) + println(yaml.encodeToString(IrWorld.serializer(), irWorld)) } private fun printCompiledWorld(compiledWorld: CompiledWorld) { diff --git a/vm/src/main/kotlin/gay/pizza/pork/vm/InternalMachine.kt b/vm/src/main/kotlin/gay/pizza/pork/vm/InternalMachine.kt index 1bf37c0..5fc04f4 100644 --- a/vm/src/main/kotlin/gay/pizza/pork/vm/InternalMachine.kt +++ b/vm/src/main/kotlin/gay/pizza/pork/vm/InternalMachine.kt @@ -13,8 +13,8 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist private var inst: UInt = 0u private val stack = mutableListOf() - private val locals = mutableListOf>( - mutableMapOf() + private val locals = mutableListOf( + LocalSlots() ) private val callStack = mutableListOf(0u) private val returnAddressStack = mutableListOf() @@ -32,7 +32,7 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist } fun pushScope() { - locals.add(mutableMapOf()) + locals.add(LocalSlots()) } fun popScope() { @@ -43,14 +43,13 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist val constant = world.constantPool.constants[id.toInt()] when (constant.tag) { ConstantTag.String -> push(String(constant.value)) - else -> throw VirtualMachineException("Unknown Constant Tag: ${constant.tag.name}") + else -> throw VirtualMachineException("Unknown constant tag: ${constant.tag.name}") } } fun localAt(id: UInt): Any { val localSet = locals.last() - return localSet[id] ?: - throw VirtualMachineException("Attempted to load local $id but it was not stored.") + return localSet.load(id) } fun loadLocal(id: UInt) { @@ -60,7 +59,7 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist fun storeLocal(id: UInt) { val localSet = locals.last() val value = popAnyValue() - localSet[id] = value + localSet.store(id, value) } fun setNextInst(value: UInt) { @@ -106,7 +105,7 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist callStack.clear() callStack.add(0u) locals.clear() - locals.add(mutableMapOf()) + locals.add(LocalSlots()) inst = 0u exitFlag = false autoNextInst = true diff --git a/vm/src/main/kotlin/gay/pizza/pork/vm/LocalSlots.kt b/vm/src/main/kotlin/gay/pizza/pork/vm/LocalSlots.kt new file mode 100644 index 0000000..6fe0dfd --- /dev/null +++ b/vm/src/main/kotlin/gay/pizza/pork/vm/LocalSlots.kt @@ -0,0 +1,25 @@ +package gay.pizza.pork.vm + +class LocalSlots { + private var slots = arrayOfNulls(4) + + fun load(index: UInt): Any { + return slots[index.toInt()] + ?: throw VirtualMachineException("Attempted to access local $index that is not stored") + } + + fun store(index: UInt, value: Any) { + if (index >= slots.size.toUInt()) { + resize(index + 4u) + } + slots[index.toInt()] = value + } + + private fun resize(count: UInt) { + val values = arrayOfNulls(count.toInt()) + for ((i, value) in slots.withIndex()) { + values[i] = value + } + slots = values + } +} diff --git a/vm/src/main/kotlin/gay/pizza/pork/vm/ops/AndOpHandler.kt b/vm/src/main/kotlin/gay/pizza/pork/vm/ops/AndOpHandler.kt index afc1e01..07c34c3 100644 --- a/vm/src/main/kotlin/gay/pizza/pork/vm/ops/AndOpHandler.kt +++ b/vm/src/main/kotlin/gay/pizza/pork/vm/ops/AndOpHandler.kt @@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler object AndOpHandler : OpHandler(Opcode.And) { override fun handle(machine: InternalMachine, op: Op) { - val left = machine.pop() val right = machine.pop() + val left = machine.pop() machine.push(left && right) } } diff --git a/vm/src/main/kotlin/gay/pizza/pork/vm/ops/MultiplyOpHandler.kt b/vm/src/main/kotlin/gay/pizza/pork/vm/ops/MultiplyOpHandler.kt index e44ee98..b4c5bf2 100644 --- a/vm/src/main/kotlin/gay/pizza/pork/vm/ops/MultiplyOpHandler.kt +++ b/vm/src/main/kotlin/gay/pizza/pork/vm/ops/MultiplyOpHandler.kt @@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler object MultiplyOpHandler : OpHandler(Opcode.Multiply) { override fun handle(machine: InternalMachine, op: Op) { - val left = machine.pop() val right = machine.pop() + val left = machine.pop() machine.push(left * right) } } diff --git a/vm/src/main/kotlin/gay/pizza/pork/vm/ops/OrOpHandler.kt b/vm/src/main/kotlin/gay/pizza/pork/vm/ops/OrOpHandler.kt index 48c348e..9ac2fc5 100644 --- a/vm/src/main/kotlin/gay/pizza/pork/vm/ops/OrOpHandler.kt +++ b/vm/src/main/kotlin/gay/pizza/pork/vm/ops/OrOpHandler.kt @@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler object OrOpHandler : OpHandler(Opcode.Or) { override fun handle(machine: InternalMachine, op: Op) { - val left = machine.pop() val right = machine.pop() + val left = machine.pop() machine.push(left || right) } }