-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
92 changed files
with
1,650 additions
and
241 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
ast/src/main/kotlin/gay/pizza/pork/ast/FunctionLevelVisitor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package gay.pizza.pork.ast | ||
|
||
import gay.pizza.pork.ast.gen.* | ||
|
||
abstract class FunctionLevelVisitor<T> : NodeVisitor<T> { | ||
override fun visitForInItem(node: ForInItem): T = | ||
throw RuntimeException("Visiting ForInItem is not supported.") | ||
|
||
override fun visitSymbol(node: Symbol): T = | ||
throw RuntimeException("Visiting Symbol is not supported.") | ||
|
||
override fun visitLetDefinition(node: LetDefinition): T { | ||
topLevelUsedError("LetDefinition") | ||
} | ||
|
||
override fun visitArgumentSpec(node: ArgumentSpec): T = | ||
throw RuntimeException("Visiting ArgumentSpec is not supported.") | ||
|
||
override fun visitFunctionDefinition(node: FunctionDefinition): T { | ||
topLevelUsedError("FunctionDefinition") | ||
} | ||
|
||
override fun visitImportDeclaration(node: ImportDeclaration): T { | ||
topLevelUsedError("ImportDeclaration") | ||
} | ||
|
||
override fun visitImportPath(node: ImportPath): T { | ||
topLevelUsedError("ImportPath") | ||
} | ||
|
||
override fun visitCompilationUnit(node: CompilationUnit): T { | ||
topLevelUsedError("CompilationUnit") | ||
} | ||
|
||
override fun visitNativeFunctionDescriptor(node: NativeFunctionDescriptor): T { | ||
topLevelUsedError("NativeFunctionDescriptor") | ||
} | ||
|
||
private fun topLevelUsedError(name: String): Nothing { | ||
throw RuntimeException("$name cannot be visited in a FunctionVisitor.") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
plugins { | ||
id("gay.pizza.pork.module") | ||
} | ||
|
||
dependencies { | ||
implementation(project(":common")) | ||
} |
10 changes: 10 additions & 0 deletions
10
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/CompiledWorld.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class CompiledWorld( | ||
val constantPool: ConstantPool, | ||
val symbolTable: SymbolTable, | ||
val code: List<Op> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
class Constant(val id: UInt, val value: ByteArray) |
6 changes: 6 additions & 0 deletions
6
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/ConstantPool.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ConstantPool(val constants: List<ByteArray>) |
18 changes: 18 additions & 0 deletions
18
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/MutableConstantPool.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
class MutableConstantPool { | ||
private val pool = mutableListOf<Constant>() | ||
|
||
fun assign(content: ByteArray): UInt { | ||
for (constant in pool) { | ||
if (constant.value.contentEquals(content)) { | ||
return constant.id | ||
} | ||
} | ||
val id = pool.size.toUInt() | ||
pool.add(Constant(id, content)) | ||
return id | ||
} | ||
|
||
fun all(): List<Constant> = pool | ||
} |
3 changes: 3 additions & 0 deletions
3
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/MutableRel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
class MutableRel(var rel: UInt) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Op(val code: Opcode, val args: List<UInt>) |
43 changes: 43 additions & 0 deletions
43
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/Opcode.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
enum class Opcode(val id: UByte) { | ||
Constant(1u), | ||
None(2u), | ||
False(3u), | ||
True(4u), | ||
Pop(5u), | ||
Jump(6u), | ||
JumpIf(7u), | ||
Not(8u), | ||
UnaryPlus(9u), | ||
UnaryMinus(10u), | ||
BinaryNot(11u), | ||
And(20u), | ||
Native(24u), | ||
Return(10u), | ||
StoreLocal(16u), | ||
LoadLocal(17u), | ||
Add(18u), | ||
Subtract(19u), | ||
Multiply(20u), | ||
Divide(21u), | ||
CompareEqual(22u), | ||
CompareLesser(23u), | ||
CompareGreater(24u), | ||
CompareLesserEqual(25u), | ||
CompareGreaterEqual(26u), | ||
Or(27u), | ||
BinaryAnd(28u), | ||
BinaryOr(29u), | ||
BinaryXor(30u), | ||
List(31u), | ||
Integer(32u), | ||
Double(33u), | ||
Call(34u), | ||
EuclideanModulo(35u), | ||
Remainder(36u), | ||
Index(37u), | ||
ScopeIn(38u), | ||
ScopeOut(39u), | ||
End(255u), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
class Ops(val ops: List<Op>) |
10 changes: 10 additions & 0 deletions
10
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/SymbolInfo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class SymbolInfo( | ||
val id: String, | ||
val offset: UInt, | ||
val size: UInt | ||
) |
8 changes: 8 additions & 0 deletions
8
bytecode/src/main/kotlin/gay/pizza/pork/bytecode/SymbolTable.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package gay.pizza.pork.bytecode | ||
|
||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class SymbolTable( | ||
val symbols: List<SymbolInfo> | ||
) |
40 changes: 40 additions & 0 deletions
40
common/src/main/kotlin/gay/pizza/pork/common/ByteRepresentation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package gay.pizza.pork.common | ||
|
||
object ByteRepresentation { | ||
fun encode(value: Int): ByteArray { | ||
val buffer = ByteArray(4) | ||
encode(value, buffer, 0) | ||
return buffer | ||
} | ||
|
||
fun encode(value: Long): ByteArray { | ||
val buffer = ByteArray(8) | ||
encode(value, buffer, 0) | ||
return buffer | ||
} | ||
|
||
fun encode(value: Double): ByteArray = | ||
encode(value.toRawBits()) | ||
|
||
fun encode(value: Int, buffer: ByteArray, offset: Int) { | ||
buffer[offset + 0] = (value shr 0).toByte() | ||
buffer[offset + 1] = (value shr 8).toByte() | ||
buffer[offset + 2] = (value shr 16).toByte() | ||
buffer[offset + 3] = (value shr 24).toByte() | ||
} | ||
|
||
fun encode(value: Long, buffer: ByteArray, offset: Int) { | ||
buffer[offset + 0] = (value shr 0).toByte() | ||
buffer[offset + 1] = (value shr 8).toByte() | ||
buffer[offset + 2] = (value shr 16).toByte() | ||
buffer[offset + 3] = (value shr 24).toByte() | ||
buffer[offset + 4] = (value shr 32).toByte() | ||
buffer[offset + 5] = (value shr 40).toByte() | ||
buffer[offset + 6] = (value shr 48).toByte() | ||
buffer[offset + 7] = (value shr 56).toByte() | ||
} | ||
|
||
fun encode(value: Double, buffer: ByteArray, offset: Int) { | ||
encode(value.toRawBits(), buffer, offset) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
plugins { | ||
id("gay.pizza.pork.module") | ||
} | ||
|
||
dependencies { | ||
api(project(":ast")) | ||
api(project(":bytecode")) | ||
api(project(":parser")) | ||
api(project(":frontend")) | ||
implementation(project(":common")) | ||
} |
16 changes: 16 additions & 0 deletions
16
compiler/src/main/kotlin/gay/pizza/pork/compiler/CompilableSlab.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
import gay.pizza.pork.ast.gen.Symbol | ||
import gay.pizza.pork.frontend.Slab | ||
|
||
class CompilableSlab(val compiler: Compiler, val slab: Slab) { | ||
val compilableSymbols: List<CompilableSymbol> by lazy { | ||
slab.scope.internalSymbols.map { symbol -> | ||
CompilableSymbol(this, symbol) | ||
} | ||
} | ||
|
||
fun compilableSymbolOf(symbol: Symbol): CompilableSymbol? = compilableSymbols.firstOrNull { | ||
it.scopeSymbol.symbol == symbol | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
compiler/src/main/kotlin/gay/pizza/pork/compiler/CompilableSymbol.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
import gay.pizza.pork.ast.gen.FunctionDefinition | ||
import gay.pizza.pork.ast.gen.LetDefinition | ||
import gay.pizza.pork.ast.gen.visit | ||
import gay.pizza.pork.frontend.scope.ScopeSymbol | ||
|
||
class CompilableSymbol(val compilableSlab: CompilableSlab, val scopeSymbol: ScopeSymbol) { | ||
val compiledStubOps: List<StubOp> by lazy { compile() } | ||
|
||
val usedSymbols: List<ScopeSymbol> | ||
get() = scopeSymbol.scope.usedSymbols | ||
|
||
private fun compile(): List<StubOp> { | ||
val emitter = StubOpEmitter(compilableSlab.compiler, this) | ||
emitter.enter() | ||
val what = if (scopeSymbol.definition is FunctionDefinition) { | ||
val functionDefinition = scopeSymbol.definition as FunctionDefinition | ||
emitter.allocateOuterScope(functionDefinition) | ||
functionDefinition.block ?: functionDefinition.nativeFunctionDescriptor!! | ||
} else { | ||
val letDefinition = scopeSymbol.definition as LetDefinition | ||
letDefinition.value | ||
} | ||
emitter.visit(what) | ||
emitter.exit() | ||
return emitter.ops() | ||
} | ||
|
||
val id: String | ||
get() = "${compilableSlab.slab.location.commonFriendlyName} ${scopeSymbol.symbol.id}" | ||
|
||
override fun toString(): String = "${compilableSlab.slab.location.commonFriendlyName} ${scopeSymbol.symbol.id}" | ||
} |
38 changes: 38 additions & 0 deletions
38
compiler/src/main/kotlin/gay/pizza/pork/compiler/CompiledWorldLayout.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
import gay.pizza.pork.bytecode.* | ||
|
||
class CompiledWorldLayout(val compiler: Compiler) : StubResolutionContext { | ||
private val allStubOps = mutableListOf<StubOp>() | ||
private val symbolTable = mutableMapOf<CompilableSymbol, SymbolInfo>() | ||
|
||
fun add(symbol: CompilableSymbol) { | ||
val start = allStubOps.size | ||
val stubOps = symbol.compiledStubOps | ||
symbolTable[symbol] = SymbolInfo(symbol.id, start.toUInt(), stubOps.size.toUInt()) | ||
allStubOps.addAll(stubOps) | ||
} | ||
|
||
private fun patch(): List<Op> { | ||
val ops = mutableListOf<Op>() | ||
for (stub in allStubOps) { | ||
val actualArguments = stub.op.args.toMutableList() | ||
stub.patch(this, actualArguments) | ||
ops.add(Op(stub.op.code, actualArguments)) | ||
} | ||
return ops | ||
} | ||
|
||
override fun resolveJumpTarget(symbol: CompilableSymbol): UInt { | ||
return symbolTable[symbol]?.offset ?: | ||
throw RuntimeException("Unable to resolve jump target: ${symbol.scopeSymbol.symbol.id}") | ||
} | ||
|
||
fun layoutCompiledWorld(): CompiledWorld { | ||
val constantPool = mutableListOf<ByteArray>() | ||
for (item in compiler.constantPool.all()) { | ||
constantPool.add(item.value) | ||
} | ||
return CompiledWorld(ConstantPool(constantPool), SymbolTable(symbolTable.values.toList()), patch()) | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
compiler/src/main/kotlin/gay/pizza/pork/compiler/Compiler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
import gay.pizza.pork.bytecode.CompiledWorld | ||
import gay.pizza.pork.bytecode.MutableConstantPool | ||
import gay.pizza.pork.frontend.Slab | ||
import gay.pizza.pork.frontend.scope.ScopeSymbol | ||
|
||
class Compiler { | ||
val constantPool: MutableConstantPool = MutableConstantPool() | ||
val compilableSlabs: ComputableState<Slab, CompilableSlab> = ComputableState { slab -> | ||
CompilableSlab(this, slab) | ||
} | ||
|
||
fun resolveOrNull(scopeSymbol: ScopeSymbol): CompilableSymbol? { | ||
val compiledSlab = compilableSlabs.of(scopeSymbol.slabScope.slab) | ||
return compiledSlab.compilableSymbolOf(scopeSymbol.symbol) | ||
} | ||
|
||
fun resolve(scopeSymbol: ScopeSymbol): CompilableSymbol = resolveOrNull(scopeSymbol) ?: | ||
throw RuntimeException( | ||
"Unable to resolve scope symbol: " + | ||
"${scopeSymbol.slabScope.slab.location.commonFriendlyName} ${scopeSymbol.symbol.id}") | ||
|
||
fun contributeCompiledSymbols( | ||
into: MutableSet<CompilableSymbol>, | ||
symbol: ScopeSymbol, | ||
resolved: CompilableSymbol = resolve(symbol) | ||
) { | ||
if (!into.add(resolved)) { | ||
return | ||
} | ||
|
||
for (used in resolved.usedSymbols) { | ||
contributeCompiledSymbols(into, used) | ||
} | ||
} | ||
|
||
fun compile(entryPointSymbol: CompilableSymbol): CompiledWorld { | ||
val usedSymbolSet = mutableSetOf<CompilableSymbol>() | ||
contributeCompiledSymbols(usedSymbolSet, entryPointSymbol.scopeSymbol, entryPointSymbol) | ||
val layout = CompiledWorldLayout(this) | ||
for (used in usedSymbolSet) { | ||
layout.add(used) | ||
} | ||
return layout.layoutCompiledWorld() | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
compiler/src/main/kotlin/gay/pizza/pork/compiler/ComputableState.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
class ComputableState<X, T>(val computation: (X) -> T) { | ||
private val state = StoredState<X, T>() | ||
|
||
fun of(key: X): T = state.computeIfAbsent(key, computation) | ||
} |
11 changes: 11 additions & 0 deletions
11
compiler/src/main/kotlin/gay/pizza/pork/compiler/LoopState.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
import gay.pizza.pork.bytecode.MutableRel | ||
|
||
class LoopState( | ||
val startOfLoop: UInt, | ||
val exitJumpTarget: MutableRel, | ||
val body: MutableRel, | ||
val scopeDepth: Int, | ||
val enclosing: LoopState? = null | ||
) |
12 changes: 12 additions & 0 deletions
12
compiler/src/main/kotlin/gay/pizza/pork/compiler/PatchRelOp.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package gay.pizza.pork.compiler | ||
|
||
import gay.pizza.pork.bytecode.MutableRel | ||
import gay.pizza.pork.bytecode.Op | ||
|
||
class PatchRelOp(op: Op, val index: Int, val symbol: CompilableSymbol, val rel: MutableRel) : StubOp(op) { | ||
override fun patch(context: StubResolutionContext, arguments: MutableList<UInt>) { | ||
arguments[index] = context.resolveJumpTarget(symbol) + rel.rel | ||
} | ||
|
||
override fun toString(): String = "PatchRelOp(${op}, ${index}, ${symbol}, ${rel})" | ||
} |
Oops, something went wrong.