mirror of
				https://github.com/GayPizzaSpecifications/pork.git
				synced 2025-11-03 17:39:38 +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