mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 21:21:33 +00:00
language: implement proper virtual machine support
This commit is contained in:
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrBreak(val target: IrSymbol) : IrCodeElement {
|
data class IrBreak(val target: IrSymbol) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(target)
|
block(target)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrCall(
|
data class IrCall(
|
||||||
override val target: IrSymbol,
|
override val target: IrSymbol,
|
||||||
val arguments: List<IrCodeElement>,
|
val arguments: List<IrCodeElement>,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrCodeBlock(val items: List<IrCodeElement>) : IrCodeElement {
|
data class IrCodeBlock(val items: List<IrCodeElement>) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
items.forEach(block)
|
items.forEach(block)
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed interface IrCodeElement : IrElement
|
sealed interface IrCodeElement : IrElement
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
package gay.pizza.pork.compiler
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
import gay.pizza.pork.bir.*
|
|
||||||
|
|
||||||
interface IrCodeVisitor<T> : IrVisitor<T> {
|
interface IrCodeVisitor<T> : IrVisitor<T> {
|
||||||
override fun visitIrDefinition(ir: IrDefinition): T {
|
override fun visitIrDefinition(ir: IrDefinition): T {
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrConditional(
|
data class IrConditional(
|
||||||
val conditional: IrCodeElement,
|
val conditional: IrCodeElement,
|
||||||
val ifTrue: IrCodeElement,
|
val ifTrue: IrCodeElement,
|
||||||
|
@ -1,12 +1,26 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed interface IrConstant : IrCodeElement {
|
sealed interface IrConstant : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {}
|
override fun crawl(block: (IrElement) -> Unit) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrIntegerConstant(val value: Int) : IrConstant
|
data class IrIntegerConstant(val value: Int) : IrConstant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrLongConstant(val value: Long) : IrConstant
|
data class IrLongConstant(val value: Long) : IrConstant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrDoubleConstant(val value: Double) : IrConstant
|
data class IrDoubleConstant(val value: Double) : IrConstant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrStringConstant(val value: String) : IrConstant
|
data class IrStringConstant(val value: String) : IrConstant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrBooleanConstant(val value: Boolean) : IrConstant
|
data class IrBooleanConstant(val value: Boolean) : IrConstant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data object IrNoneConstant : IrConstant
|
data object IrNoneConstant : IrConstant
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrContinue(override val target: IrSymbol) : IrCodeElement, IrSymbolUser {
|
data class IrContinue(override val target: IrSymbol) : IrCodeElement, IrSymbolUser {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(target)
|
block(target)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrDefinition(
|
data class IrDefinition(
|
||||||
override val symbol: IrSymbol,
|
override val symbol: IrSymbol,
|
||||||
val type: IrDefinitionType,
|
val type: IrDefinitionType,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
enum class IrDefinitionType {
|
enum class IrDefinitionType {
|
||||||
Variable,
|
Variable,
|
||||||
CodeFunction,
|
CodeFunction,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed interface IrElement {
|
sealed interface IrElement {
|
||||||
fun crawl(block: (IrElement) -> Unit)
|
fun crawl(block: (IrElement) -> Unit)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrFunctionArgument(override val symbol: IrSymbol) : IrSymbolOwner {
|
data class IrFunctionArgument(override val symbol: IrSymbol) : IrSymbolOwner {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {}
|
override fun crawl(block: (IrElement) -> Unit) {}
|
||||||
}
|
}
|
||||||
|
11
bir/src/main/kotlin/gay/pizza/pork/bir/IrIndex.kt
Normal file
11
bir/src/main/kotlin/gay/pizza/pork/bir/IrIndex.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class IrIndex(val data: IrCodeElement, val index: IrCodeElement) : IrCodeElement {
|
||||||
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
|
block(data)
|
||||||
|
block(index)
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrInfix(val op: IrInfixOp, val left: IrCodeElement, val right: IrCodeElement) : IrCodeElement {
|
data class IrInfix(val op: IrInfixOp, val left: IrCodeElement, val right: IrCodeElement) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(left)
|
block(left)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
enum class IrInfixOp {
|
enum class IrInfixOp {
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrList(val items: List<IrCodeElement>) : IrCodeElement {
|
data class IrList(val items: List<IrCodeElement>) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
items.forEach(block)
|
items.forEach(block)
|
||||||
|
10
bir/src/main/kotlin/gay/pizza/pork/bir/IrListSize.kt
Normal file
10
bir/src/main/kotlin/gay/pizza/pork/bir/IrListSize.kt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class IrListSize(val list: IrCodeElement) : IrCodeElement {
|
||||||
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
|
block(list)
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrLoad(override val target: IrSymbol) : IrCodeElement, IrSymbolUser {
|
data class IrLoad(override val target: IrSymbol) : IrCodeElement, IrSymbolUser {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(target)
|
block(target)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrLoop(
|
data class IrLoop(
|
||||||
override val symbol: IrSymbol,
|
override val symbol: IrSymbol,
|
||||||
val condition: IrCodeElement,
|
val condition: IrCodeElement,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrNativeDefinition(val form: String, val definitions: List<String>) : IrCodeElement {
|
data class IrNativeDefinition(val form: String, val definitions: List<String>) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {}
|
override fun crawl(block: (IrElement) -> Unit) {}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrPrefix(val op: IrPrefixOp, val value: IrCodeElement) : IrCodeElement {
|
data class IrPrefix(val op: IrPrefixOp, val value: IrCodeElement) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(value)
|
block(value)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
enum class IrPrefixOp {
|
enum class IrPrefixOp {
|
||||||
BooleanNot,
|
BooleanNot,
|
||||||
UnaryPlus,
|
UnaryPlus,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrReturn(val from: IrSymbol, val value: IrCodeElement) : IrCodeElement {
|
data class IrReturn(val from: IrSymbol, val value: IrCodeElement) : IrCodeElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(from)
|
block(from)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrSlab(
|
data class IrSlab(
|
||||||
val location: IrSlabLocation,
|
val location: IrSlabLocation,
|
||||||
val definitions: List<IrDefinition>
|
val definitions: List<IrDefinition>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrSlabLocation(
|
data class IrSlabLocation(
|
||||||
val form: String,
|
val form: String,
|
||||||
val path: String
|
val path: String
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrStore(override val target: IrSymbol, val value: IrCodeElement) : IrCodeElement, IrSymbolUser {
|
data class IrStore(override val target: IrSymbol, val value: IrCodeElement) : IrCodeElement, IrSymbolUser {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
value.crawl(block)
|
value.crawl(block)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrSuffix(val op: IrSuffixOp, override val target: IrSymbol) : IrCodeElement, IrSymbolUser {
|
data class IrSuffix(val op: IrSuffixOp, override val target: IrSymbol) : IrCodeElement, IrSymbolUser {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
block(target)
|
block(target)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
enum class IrSuffixOp {
|
enum class IrSuffixOp {
|
||||||
Increment,
|
Increment,
|
||||||
Decrement
|
Decrement
|
||||||
|
@ -1,5 +1,24 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
data class IrSymbol(val id: UInt, val tag: IrSymbolTag) : IrElement {
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class IrSymbol(val id: UInt, val tag: IrSymbolTag, val name: String? = null) : IrElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {}
|
override fun crawl(block: (IrElement) -> Unit) {}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is IrSymbol) return false
|
||||||
|
return other.id == id && other.tag == tag
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = id.hashCode()
|
||||||
|
result = 31 * result + tag.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
val friendlyName: String
|
||||||
|
get() = if (name != null) {
|
||||||
|
"$id $tag $name"
|
||||||
|
} else "$id $tag"
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,6 @@ class IrSymbolAssignment {
|
|||||||
private var index = 0u
|
private var index = 0u
|
||||||
|
|
||||||
private fun nextSymbolId(): UInt = index++
|
private fun nextSymbolId(): UInt = index++
|
||||||
fun next(tag: IrSymbolTag): IrSymbol = IrSymbol(nextSymbolId(), tag)
|
fun next(tag: IrSymbolTag, name: String? = null): IrSymbol =
|
||||||
|
IrSymbol(id = nextSymbolId(), tag = tag, name = name)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed interface IrSymbolOwner : IrElement {
|
sealed interface IrSymbolOwner : IrElement {
|
||||||
val symbol: IrSymbol
|
val symbol: IrSymbol
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
enum class IrSymbolTag {
|
enum class IrSymbolTag {
|
||||||
Function,
|
Function,
|
||||||
Variable,
|
Variable,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed interface IrSymbolUser : IrElement {
|
sealed interface IrSymbolUser : IrElement {
|
||||||
val target: IrSymbol
|
val target: IrSymbol
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ interface IrVisitor<T> {
|
|||||||
fun visitIrWorld(ir: IrWorld): T
|
fun visitIrWorld(ir: IrWorld): T
|
||||||
fun visitIrNativeDefinition(ir: IrNativeDefinition): T
|
fun visitIrNativeDefinition(ir: IrNativeDefinition): T
|
||||||
fun visitIrFunctionArgument(ir: IrFunctionArgument): T
|
fun visitIrFunctionArgument(ir: IrFunctionArgument): T
|
||||||
|
fun visitIrIndex(ir: IrIndex): T
|
||||||
|
fun visitIrListSize(ir: IrListSize): T
|
||||||
|
|
||||||
fun visit(ir: IrElement): T = when (ir) {
|
fun visit(ir: IrElement): T = when (ir) {
|
||||||
is IrBreak -> visitIrBeak(ir)
|
is IrBreak -> visitIrBeak(ir)
|
||||||
@ -55,5 +57,7 @@ interface IrVisitor<T> {
|
|||||||
is IrWorld -> visitIrWorld(ir)
|
is IrWorld -> visitIrWorld(ir)
|
||||||
is IrNativeDefinition -> visitIrNativeDefinition(ir)
|
is IrNativeDefinition -> visitIrNativeDefinition(ir)
|
||||||
is IrFunctionArgument -> visitIrFunctionArgument(ir)
|
is IrFunctionArgument -> visitIrFunctionArgument(ir)
|
||||||
|
is IrIndex -> visitIrIndex(ir)
|
||||||
|
is IrListSize -> visitIrListSize(ir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package gay.pizza.pork.bir
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class IrWorld(val slabs: List<IrSlab>) : IrElement {
|
data class IrWorld(val slabs: List<IrSlab>) : IrElement {
|
||||||
override fun crawl(block: (IrElement) -> Unit) {
|
override fun crawl(block: (IrElement) -> Unit) {
|
||||||
slabs.forEach(block)
|
slabs.forEach(block)
|
||||||
|
@ -33,13 +33,14 @@ enum class Opcode(val id: UByte) {
|
|||||||
ListMake(31u),
|
ListMake(31u),
|
||||||
ListSize(32u),
|
ListSize(32u),
|
||||||
Integer(33u),
|
Integer(33u),
|
||||||
Double(34u),
|
Long(34u),
|
||||||
Call(35u),
|
Double(35u),
|
||||||
EuclideanModulo(36u),
|
Call(36u),
|
||||||
Remainder(37u),
|
EuclideanModulo(37u),
|
||||||
Index(38u),
|
Remainder(38u),
|
||||||
ScopeIn(39u),
|
Index(39u),
|
||||||
ScopeOut(40u),
|
ScopeIn(40u),
|
||||||
ReturnAddress(41u),
|
ScopeOut(41u),
|
||||||
|
ReturnAddress(42u),
|
||||||
End(255u),
|
End(255u),
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,6 @@ class CompilableSlab(val compiler: Compiler, val slab: Slab) {
|
|||||||
it.scopeSymbol.symbol == symbol
|
it.scopeSymbol.symbol == symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveVisible(symbol: Symbol): CompilableSymbol? {
|
|
||||||
val scopeSymbol = slab.scope.resolve(symbol) ?: return null
|
|
||||||
return compiler.resolveOrNull(scopeSymbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun compileIrSlab(): IrSlab {
|
private fun compileIrSlab(): IrSlab {
|
||||||
val definitions = mutableListOf<IrDefinition>()
|
val definitions = mutableListOf<IrDefinition>()
|
||||||
for (compilableSymbol in compilableSymbols) {
|
for (compilableSymbol in compilableSymbols) {
|
||||||
|
@ -28,7 +28,7 @@ class CompilableSymbol(val compilableSlab: CompilableSlab, val scopeSymbol: Scop
|
|||||||
|
|
||||||
private fun compileIrDefinition(): IrDefinition {
|
private fun compileIrDefinition(): IrDefinition {
|
||||||
val compiler = compilableSlab.compiler
|
val compiler = compilableSlab.compiler
|
||||||
val functionSymbol = compiler.irSymbolWorld.create(scopeSymbol, IrSymbolTag.Function)
|
val functionSymbol = compiler.irSymbolWorld.create(scopeSymbol, IrSymbolTag.Function, scopeSymbol.symbol.id)
|
||||||
val irCodeEmitter = IrCodeEmitter(
|
val irCodeEmitter = IrCodeEmitter(
|
||||||
self = functionSymbol,
|
self = functionSymbol,
|
||||||
irSymbolWorld = compiler.irSymbolWorld,
|
irSymbolWorld = compiler.irSymbolWorld,
|
||||||
|
@ -13,7 +13,7 @@ class CompiledWorldLayout(val compiler: Compiler) : StubResolutionContext {
|
|||||||
val stubOps = result.ops
|
val stubOps = result.ops
|
||||||
symbolTable[symbol] = SymbolInfo(
|
symbolTable[symbol] = SymbolInfo(
|
||||||
slab = symbol.compilableSlab.slab.location.commonLocationIdentity,
|
slab = symbol.compilableSlab.slab.location.commonLocationIdentity,
|
||||||
symbol = symbol.id,
|
symbol = symbol.scopeSymbol.symbol.id,
|
||||||
offset = start.toUInt(),
|
offset = start.toUInt(),
|
||||||
size = stubOps.size.toUInt()
|
size = stubOps.size.toUInt()
|
||||||
)
|
)
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package gay.pizza.pork.compiler
|
package gay.pizza.pork.compiler
|
||||||
|
|
||||||
|
import gay.pizza.pork.bir.IrSlab
|
||||||
import gay.pizza.pork.bir.IrSymbolAssignment
|
import gay.pizza.pork.bir.IrSymbolAssignment
|
||||||
|
import gay.pizza.pork.bir.IrWorld
|
||||||
import gay.pizza.pork.bytecode.CompiledWorld
|
import gay.pizza.pork.bytecode.CompiledWorld
|
||||||
import gay.pizza.pork.bytecode.MutableConstantPool
|
import gay.pizza.pork.bytecode.MutableConstantPool
|
||||||
import gay.pizza.pork.frontend.Slab
|
import gay.pizza.pork.frontend.Slab
|
||||||
|
import gay.pizza.pork.frontend.World
|
||||||
import gay.pizza.pork.frontend.scope.ScopeSymbol
|
import gay.pizza.pork.frontend.scope.ScopeSymbol
|
||||||
|
|
||||||
class Compiler {
|
class Compiler(val world: World) {
|
||||||
val constantPool: MutableConstantPool = MutableConstantPool()
|
val constantPool: MutableConstantPool = MutableConstantPool()
|
||||||
val compilableSlabs: ComputableState<Slab, CompilableSlab> = ComputableState { slab ->
|
val compilableSlabs: ComputableState<Slab, CompilableSlab> = ComputableState { slab ->
|
||||||
CompilableSlab(this, slab)
|
CompilableSlab(this, slab)
|
||||||
@ -39,6 +42,14 @@ class Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun compileIrWorld(): IrWorld {
|
||||||
|
val slabs = mutableListOf<IrSlab>()
|
||||||
|
for (slab in world.slabs) {
|
||||||
|
slabs.add(compilableSlabs.of(slab).compiledIrSlab)
|
||||||
|
}
|
||||||
|
return IrWorld(slabs)
|
||||||
|
}
|
||||||
|
|
||||||
fun compile(entryPointSymbol: CompilableSymbol): CompiledWorld {
|
fun compile(entryPointSymbol: CompilableSymbol): CompiledWorld {
|
||||||
val usedSymbolSet = mutableSetOf<CompilableSymbol>()
|
val usedSymbolSet = mutableSetOf<CompilableSymbol>()
|
||||||
contributeCompiledSymbols(usedSymbolSet, entryPointSymbol.scopeSymbol, entryPointSymbol)
|
contributeCompiledSymbols(usedSymbolSet, entryPointSymbol.scopeSymbol, entryPointSymbol)
|
||||||
|
@ -13,7 +13,7 @@ class IrCodeEmitter(
|
|||||||
val scope: SlabScope
|
val scope: SlabScope
|
||||||
) : FunctionLevelVisitor<IrCodeElement>() {
|
) : FunctionLevelVisitor<IrCodeElement>() {
|
||||||
private val loopSymbols = mutableListOf<IrSymbol>()
|
private val loopSymbols = mutableListOf<IrSymbol>()
|
||||||
private val localVariables = mutableListOf<MutableMap<String, LocalVariable>>()
|
private val localVariables = mutableListOf<MutableMap<Pair<String?, UInt?>, LocalVariable>>()
|
||||||
|
|
||||||
var functionArguments: List<IrFunctionArgument> = emptyList()
|
var functionArguments: List<IrFunctionArgument> = emptyList()
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class IrCodeEmitter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun enterLocalScope() {
|
fun enterLocalScope() {
|
||||||
val locals = mutableMapOf<String, LocalVariable>()
|
val locals = mutableMapOf<Pair<String?, UInt?>, LocalVariable>()
|
||||||
localVariables.add(locals)
|
localVariables.add(locals)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,15 +54,16 @@ class IrCodeEmitter(
|
|||||||
localVariables.removeLast()
|
localVariables.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLocalVariable(name: Symbol): IrSymbol {
|
private fun createLocalVariable(name: Symbol? = null): IrSymbol {
|
||||||
val symbol = irSymbolAssignment.next(IrSymbolTag.Local)
|
val symbol = irSymbolAssignment.next(tag = IrSymbolTag.Local, name = name?.id)
|
||||||
val variable = LocalVariable(symbol, name)
|
val variable = LocalVariable(symbol, name)
|
||||||
val variables = localVariables.last()
|
val variables = localVariables.last()
|
||||||
val existing = variables[name.id]
|
val identifier = name?.id to (if (name == null) symbol.id else null)
|
||||||
|
val existing = variables[identifier]
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
throw CompileError("Unable to define local variable '${name.id}' within this scope, it already exists", name)
|
throw CompileError("Unable to define local variable '${identifier.first}' within this scope, it already exists", name)
|
||||||
}
|
}
|
||||||
variables[name.id] = variable
|
variables[identifier] = variable
|
||||||
return symbol
|
return symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,10 +75,11 @@ class IrCodeEmitter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun lookupLocalVariable(name: Symbol): IrSymbol? {
|
private fun lookupLocalVariable(name: Symbol): IrSymbol? {
|
||||||
|
val identifier = name.id to null
|
||||||
for (i in 1..localVariables.size) {
|
for (i in 1..localVariables.size) {
|
||||||
val b = localVariables.size - i
|
val b = localVariables.size - i
|
||||||
val scope = localVariables[b]
|
val scope = localVariables[b]
|
||||||
val found = scope[name.id]
|
val found = scope[identifier]
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
return found.symbol
|
return found.symbol
|
||||||
}
|
}
|
||||||
@ -99,7 +101,7 @@ class IrCodeEmitter(
|
|||||||
|
|
||||||
private fun lookupFunction(name: Symbol): Pair<ScopeSymbol, IrSymbol>? {
|
private fun lookupFunction(name: Symbol): Pair<ScopeSymbol, IrSymbol>? {
|
||||||
val scoped = scope.resolve(name) ?: return null
|
val scoped = scope.resolve(name) ?: return null
|
||||||
return scoped to irSymbolWorld.create(scoped, scopeSymbolToTag(scoped))
|
return scoped to irSymbolWorld.create(value = scoped, tag = scopeSymbolToTag(scoped), name = scoped.symbol.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlock(node: Block): IrCodeBlock {
|
override fun visitBlock(node: Block): IrCodeBlock {
|
||||||
@ -128,7 +130,33 @@ class IrCodeEmitter(
|
|||||||
IrDoubleConstant(node.value)
|
IrDoubleConstant(node.value)
|
||||||
|
|
||||||
override fun visitForIn(node: ForIn): IrCodeElement {
|
override fun visitForIn(node: ForIn): IrCodeElement {
|
||||||
return IrNoneConstant
|
val listLocal = createLocalVariable()
|
||||||
|
val indexLocal = createLocalVariable()
|
||||||
|
val sizeLocal = createLocalVariable()
|
||||||
|
val loopSymbol = irSymbolAssignment.next(IrSymbolTag.Loop)
|
||||||
|
|
||||||
|
val items = mutableListOf<IrCodeElement>(
|
||||||
|
IrStore(listLocal, visit(node.expression)),
|
||||||
|
IrStore(indexLocal, IrIntegerConstant(0)),
|
||||||
|
IrStore(sizeLocal, IrListSize(IrLoad(listLocal)))
|
||||||
|
)
|
||||||
|
|
||||||
|
enterLocalScope()
|
||||||
|
val loopValueLocal = createLocalVariable(node.item.symbol)
|
||||||
|
val subCodeBlock = visitBlock(node.block)
|
||||||
|
val innerCodeBlock = IrCodeBlock(listOf(
|
||||||
|
IrStore(loopValueLocal, IrIndex(IrLoad(listLocal), IrLoad(indexLocal))),
|
||||||
|
IrStore(indexLocal, IrInfix(IrInfixOp.Add, IrLoad(indexLocal), IrIntegerConstant(1))),
|
||||||
|
subCodeBlock
|
||||||
|
))
|
||||||
|
exitLocalScope()
|
||||||
|
val loop = IrLoop(
|
||||||
|
symbol = loopSymbol,
|
||||||
|
condition = IrInfix(IrInfixOp.Lesser, IrLoad(indexLocal), IrLoad(sizeLocal)),
|
||||||
|
inner = innerCodeBlock
|
||||||
|
)
|
||||||
|
items.add(loop)
|
||||||
|
return IrCodeBlock(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionCall(node: FunctionCall): IrCodeElement {
|
override fun visitFunctionCall(node: FunctionCall): IrCodeElement {
|
||||||
@ -169,19 +197,20 @@ class IrCodeEmitter(
|
|||||||
variableArguments = mutableListOf()
|
variableArguments = mutableListOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
return IrCall(symbol, arguments, variableArguments)
|
return IrCall(target = symbol, arguments = arguments, variableArguments = variableArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitIf(node: If): IrCodeElement =
|
override fun visitIf(node: If): IrCodeElement =
|
||||||
IrConditional(
|
IrConditional(
|
||||||
node.condition.visit(this),
|
conditional = node.condition.visit(this),
|
||||||
node.thenBlock.visit(this),
|
ifTrue = node.thenBlock.visit(this),
|
||||||
node.elseBlock?.visit(this) ?: IrNoneConstant
|
ifFalse = node.elseBlock?.visit(this) ?: IrNoneConstant
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun visitIndexedBy(node: IndexedBy): IrCodeElement {
|
override fun visitIndexedBy(node: IndexedBy): IrCodeElement = IrIndex(
|
||||||
TODO("Not yet implemented")
|
data = visit(node.expression),
|
||||||
}
|
index = visit(node.index)
|
||||||
|
)
|
||||||
|
|
||||||
override fun visitInfixOperation(node: InfixOperation): IrCodeElement {
|
override fun visitInfixOperation(node: InfixOperation): IrCodeElement {
|
||||||
val op = when (node.op) {
|
val op = when (node.op) {
|
||||||
|
@ -74,10 +74,10 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
|
|||||||
val endRel = MutableRel(0u)
|
val endRel = MutableRel(0u)
|
||||||
visit(ir.conditional)
|
visit(ir.conditional)
|
||||||
code.patch(Opcode.JumpIf, listOf(0u), 0, symbol, thenRel)
|
code.patch(Opcode.JumpIf, listOf(0u), 0, symbol, thenRel)
|
||||||
visit(ir.ifTrue)
|
visit(ir.ifFalse)
|
||||||
code.patch(Opcode.Jump, listOf(0u), 0, symbol, endRel)
|
code.patch(Opcode.Jump, listOf(0u), 0, symbol, endRel)
|
||||||
thenRel.rel = code.nextOpInst()
|
thenRel.rel = code.nextOpInst()
|
||||||
visit(ir.ifFalse)
|
visit(ir.ifTrue)
|
||||||
endRel.rel = code.nextOpInst()
|
endRel.rel = code.nextOpInst()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,11 +90,16 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitIrLongConstant(ir: IrLongConstant) {
|
override fun visitIrLongConstant(ir: IrLongConstant) {
|
||||||
code.emit(Opcode.Integer, listOf(ir.value.toUInt()))
|
val value1 = ir.value.toUInt()
|
||||||
|
val value2 = (ir.value shr 32).toUInt()
|
||||||
|
code.emit(Opcode.Long, listOf(value1, value2))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitIrDoubleConstant(ir: IrDoubleConstant) {
|
override fun visitIrDoubleConstant(ir: IrDoubleConstant) {
|
||||||
code.emit(Opcode.Integer, listOf(ir.value.toUInt()))
|
val value = ir.value.toRawBits()
|
||||||
|
val value1 = value.toUInt()
|
||||||
|
val value2 = (value shr 32).toUInt()
|
||||||
|
code.emit(Opcode.Double, listOf(value1, value2))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitIrStringConstant(ir: IrStringConstant) {
|
override fun visitIrStringConstant(ir: IrStringConstant) {
|
||||||
@ -219,4 +224,15 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
|
|||||||
)
|
)
|
||||||
code.emit(Opcode.Native, listOf(formConstant, ir.definitions.size.toUInt(), functionArgumentCount.toUInt()))
|
code.emit(Opcode.Native, listOf(formConstant, ir.definitions.size.toUInt(), functionArgumentCount.toUInt()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitIrIndex(ir: IrIndex) {
|
||||||
|
visit(ir.index)
|
||||||
|
visit(ir.data)
|
||||||
|
code.emit(Opcode.Index)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIrListSize(ir: IrListSize) {
|
||||||
|
visit(ir.list)
|
||||||
|
code.emit(Opcode.ListSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ import gay.pizza.pork.bir.IrSymbolTag
|
|||||||
class IrSymbolWorld<T>(val irSymbolAssignment: IrSymbolAssignment) {
|
class IrSymbolWorld<T>(val irSymbolAssignment: IrSymbolAssignment) {
|
||||||
private val symbols = mutableMapOf<T, IrSymbol>()
|
private val symbols = mutableMapOf<T, IrSymbol>()
|
||||||
|
|
||||||
fun create(value: T, tag: IrSymbolTag): IrSymbol = symbols.getOrPut(value) {
|
fun create(value: T, tag: IrSymbolTag, name: String? = null): IrSymbol = symbols.getOrPut(value) {
|
||||||
irSymbolAssignment.next(tag)
|
irSymbolAssignment.next(tag, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolve(value: T): IrSymbol? = symbols[value]
|
fun resolve(value: T): IrSymbol? = symbols[value]
|
||||||
|
@ -3,4 +3,4 @@ package gay.pizza.pork.compiler
|
|||||||
import gay.pizza.pork.ast.gen.Symbol
|
import gay.pizza.pork.ast.gen.Symbol
|
||||||
import gay.pizza.pork.bir.IrSymbol
|
import gay.pizza.pork.bir.IrSymbol
|
||||||
|
|
||||||
data class LocalVariable(val symbol: IrSymbol, val name: Symbol)
|
data class LocalVariable(val symbol: IrSymbol, val name: Symbol? = null)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/* fibonacci sequence */
|
/* fibonacci sequence */
|
||||||
func fib(n) {
|
func fib(n) {
|
||||||
return if n < 2 {
|
if n < 2 {
|
||||||
n
|
return n
|
||||||
} else {
|
} else {
|
||||||
fib(n - 1) + fib(n - 2)
|
return fib(n - 1) + fib(n - 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
let items = ["Hello", "Goodbye"]
|
|
||||||
|
|
||||||
export func main() {
|
export func main() {
|
||||||
|
let items = ["Hello", "Goodbye"]
|
||||||
for item in items {
|
for item in items {
|
||||||
println(item)
|
println(item)
|
||||||
}
|
}
|
||||||
|
6
examples/list.pork
Normal file
6
examples/list.pork
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export func main() {
|
||||||
|
let items = listInitWith(30, 0)
|
||||||
|
for item in items {
|
||||||
|
println(item)
|
||||||
|
}
|
||||||
|
}
|
@ -14,5 +14,5 @@ class NativeRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun of(form: String): NativeProvider =
|
fun of(form: String): NativeProvider =
|
||||||
providers[form] ?: throw RuntimeException("Unknown native form: ${form}")
|
providers[form] ?: throw RuntimeException("Unknown native form: $form")
|
||||||
}
|
}
|
||||||
|
@ -4,21 +4,40 @@ import com.github.ajalt.clikt.core.CliktCommand
|
|||||||
import com.github.ajalt.clikt.parameters.arguments.argument
|
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||||
import gay.pizza.dough.fs.PlatformFsProvider
|
import gay.pizza.dough.fs.PlatformFsProvider
|
||||||
import gay.pizza.pork.ast.gen.Symbol
|
import gay.pizza.pork.ast.gen.Symbol
|
||||||
|
import gay.pizza.pork.bir.IrWorld
|
||||||
|
import gay.pizza.pork.bytecode.CompiledWorld
|
||||||
import gay.pizza.pork.compiler.Compiler
|
import gay.pizza.pork.compiler.Compiler
|
||||||
import gay.pizza.pork.minimal.FileTool
|
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") {
|
class CompileCommand : CliktCommand(help = "Compile Pork to Bytecode", name = "compile") {
|
||||||
val path by argument("file")
|
val path by argument("file")
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
val tool = FileTool(PlatformFsProvider.resolve(path))
|
val tool = FileTool(PlatformFsProvider.resolve(path))
|
||||||
val world = tool.buildWorld()
|
val world = tool.buildWorld()
|
||||||
val compiler = Compiler()
|
val compiler = Compiler(world)
|
||||||
val slab = world.load(tool.rootImportLocator)
|
val slab = world.load(tool.rootImportLocator)
|
||||||
val compiledSlab = compiler.compilableSlabs.of(slab)
|
val compiledSlab = compiler.compilableSlabs.of(slab)
|
||||||
val compiledMain = compiledSlab.resolve(Symbol("main"))
|
val compiledMain = compiledSlab.resolve(Symbol("main"))
|
||||||
?: throw RuntimeException("'main' function not found.")
|
?: throw RuntimeException("'main' function not found.")
|
||||||
val compiledWorld = compiler.compile(compiledMain)
|
val compiledWorld = compiler.compile(compiledMain)
|
||||||
|
val irWorld = compiler.compileIrWorld()
|
||||||
|
printCompiledIr(irWorld)
|
||||||
|
printCompiledWorld(compiledWorld)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printCompiledIr(irWorld: IrWorld) {
|
||||||
|
val json = Json {
|
||||||
|
prettyPrint = true
|
||||||
|
prettyPrintIndent = " "
|
||||||
|
}
|
||||||
|
println(json.encodeToString(IrWorld.serializer(), irWorld))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printCompiledWorld(compiledWorld: CompiledWorld) {
|
||||||
for (symbol in compiledWorld.symbolTable.symbols) {
|
for (symbol in compiledWorld.symbolTable.symbols) {
|
||||||
val code = compiledWorld.code.subList(symbol.offset.toInt(), (symbol.offset + symbol.size).toInt())
|
val code = compiledWorld.code.subList(symbol.offset.toInt(), (symbol.offset + symbol.size).toInt())
|
||||||
println(symbol.commonSymbolIdentity)
|
println(symbol.commonSymbolIdentity)
|
||||||
|
@ -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 localSet = locals.last()
|
||||||
val local = localSet[id]
|
return localSet[id] ?:
|
||||||
?: throw VirtualMachineException("Attempted to load local $id but it was not stored.")
|
throw VirtualMachineException("Attempted to load local $id but it was not stored.")
|
||||||
push(local)
|
}
|
||||||
|
|
||||||
|
fun loadLocal(id: UInt) {
|
||||||
|
push(localAt(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun storeLocal(id: UInt) {
|
fun storeLocal(id: UInt) {
|
||||||
@ -108,4 +111,11 @@ class InternalMachine(val world: CompiledWorld, val nativeRegistry: NativeRegist
|
|||||||
exitFlag = false
|
exitFlag = false
|
||||||
autoNextInst = true
|
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 {
|
class VirtualMachineProvider(val world: World) : ExecutionContextProvider {
|
||||||
override fun prepare(importLocator: ImportLocator, entryPointSymbol: Symbol, nativeRegistry: NativeRegistry): ExecutionContext {
|
override fun prepare(importLocator: ImportLocator, entryPointSymbol: Symbol, nativeRegistry: NativeRegistry): ExecutionContext {
|
||||||
val compiler = Compiler()
|
val compiler = Compiler(world)
|
||||||
val slab = world.load(importLocator)
|
val slab = world.load(importLocator)
|
||||||
val compilableSlab = compiler.compilableSlabs.of(slab)
|
val compilableSlab = compiler.compilableSlabs.of(slab)
|
||||||
val compilableSymbol = compilableSlab.resolve(entryPointSymbol) ?:
|
val compilableSymbol = compilableSlab.resolve(entryPointSymbol) ?:
|
||||||
|
@ -7,8 +7,8 @@ import gay.pizza.pork.vm.OpHandler
|
|||||||
|
|
||||||
object AddOpHandler : OpHandler(Opcode.Add) {
|
object AddOpHandler : OpHandler(Opcode.Add) {
|
||||||
override fun handle(machine: InternalMachine, op: Op) {
|
override fun handle(machine: InternalMachine, op: Op) {
|
||||||
val left = machine.pop<Int>()
|
|
||||||
val right = machine.pop<Int>()
|
val right = machine.pop<Int>()
|
||||||
|
val left = machine.pop<Int>()
|
||||||
machine.push(left + right)
|
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.Op
|
||||||
import gay.pizza.pork.bytecode.Opcode
|
import gay.pizza.pork.bytecode.Opcode
|
||||||
|
import gay.pizza.pork.execution.None
|
||||||
import gay.pizza.pork.vm.InternalMachine
|
import gay.pizza.pork.vm.InternalMachine
|
||||||
import gay.pizza.pork.vm.OpHandler
|
import gay.pizza.pork.vm.OpHandler
|
||||||
|
|
||||||
@ -9,9 +10,10 @@ object NativeOpHandler : OpHandler(Opcode.Native) {
|
|||||||
override fun handle(machine: InternalMachine, op: Op) {
|
override fun handle(machine: InternalMachine, op: Op) {
|
||||||
val argumentCount = op.args[2]
|
val argumentCount = op.args[2]
|
||||||
val arguments = mutableListOf<Any>()
|
val arguments = mutableListOf<Any>()
|
||||||
for (i in 0u until argumentCount) {
|
var x = argumentCount
|
||||||
machine.loadLocal(i)
|
while (x > 0u) {
|
||||||
arguments.add(machine.popAnyValue())
|
x--
|
||||||
|
arguments.add(machine.localAt(x))
|
||||||
}
|
}
|
||||||
val formConstant = machine.world.constantPool.read(op.args[0])
|
val formConstant = machine.world.constantPool.read(op.args[0])
|
||||||
val form = formConstant.readAsString()
|
val form = formConstant.readAsString()
|
||||||
@ -22,6 +24,7 @@ object NativeOpHandler : OpHandler(Opcode.Native) {
|
|||||||
defs.add(machine.pop())
|
defs.add(machine.pop())
|
||||||
}
|
}
|
||||||
val function = provider.provideNativeFunction(defs)
|
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) {
|
object SubtractOpHandler : OpHandler(Opcode.Subtract) {
|
||||||
override fun handle(machine: InternalMachine, op: Op) {
|
override fun handle(machine: InternalMachine, op: Op) {
|
||||||
val left = machine.pop<Int>()
|
|
||||||
val right = machine.pop<Int>()
|
val right = machine.pop<Int>()
|
||||||
|
val left = machine.pop<Int>()
|
||||||
machine.push(left - right)
|
machine.push(left - right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user