mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 21:00:56 +00:00
introduce ir nop to fix loop bugs
This commit is contained in:
parent
837e0c1b38
commit
69230deefc
5
bir/src/main/kotlin/gay/pizza/pork/bir/IrNop.kt
Normal file
5
bir/src/main/kotlin/gay/pizza/pork/bir/IrNop.kt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package gay.pizza.pork.bir
|
||||||
|
|
||||||
|
object IrNop : IrCodeElement() {
|
||||||
|
override fun crawl(block: (IrElement) -> Unit) {}
|
||||||
|
}
|
@ -30,6 +30,7 @@ interface IrVisitor<T> {
|
|||||||
fun visitIrIndex(ir: IrIndex): T
|
fun visitIrIndex(ir: IrIndex): T
|
||||||
fun visitIrListSize(ir: IrListSize): T
|
fun visitIrListSize(ir: IrListSize): T
|
||||||
fun visitIrDeclare(ir: IrDeclare): T
|
fun visitIrDeclare(ir: IrDeclare): T
|
||||||
|
fun visitIrNop(ir: IrNop): T
|
||||||
|
|
||||||
fun visit(ir: IrElement): T = when (ir) {
|
fun visit(ir: IrElement): T = when (ir) {
|
||||||
is IrBreak -> visitIrBeak(ir)
|
is IrBreak -> visitIrBeak(ir)
|
||||||
@ -61,5 +62,6 @@ interface IrVisitor<T> {
|
|||||||
is IrIndex -> visitIrIndex(ir)
|
is IrIndex -> visitIrIndex(ir)
|
||||||
is IrListSize -> visitIrListSize(ir)
|
is IrListSize -> visitIrListSize(ir)
|
||||||
is IrDeclare -> visitIrDeclare(ir)
|
is IrDeclare -> visitIrDeclare(ir)
|
||||||
|
IrNop -> visitIrNop(ir as IrNop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,26 @@ class AstIrEmitter(
|
|||||||
fun createFunctionArguments(functionDefinition: FunctionDefinition) {
|
fun createFunctionArguments(functionDefinition: FunctionDefinition) {
|
||||||
val functionSymbols = mutableListOf<IrFunctionArgument>()
|
val functionSymbols = mutableListOf<IrFunctionArgument>()
|
||||||
for (arg in functionDefinition.arguments) {
|
for (arg in functionDefinition.arguments) {
|
||||||
|
if (arg.typeSpec != null) {
|
||||||
|
validateTypeSpec(arg.typeSpec!!)
|
||||||
|
}
|
||||||
val symbol = createLocalVariable(arg.symbol)
|
val symbol = createLocalVariable(arg.symbol)
|
||||||
functionSymbols.add(IrFunctionArgument(symbol))
|
functionSymbols.add(IrFunctionArgument(symbol))
|
||||||
}
|
}
|
||||||
functionArguments = functionSymbols
|
functionArguments = functionSymbols
|
||||||
|
if (functionDefinition.returnType != null) {
|
||||||
|
validateTypeSpec(functionDefinition.returnType!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkLetDefinition(letDefinition: LetDefinition) {
|
||||||
|
if (letDefinition.typeSpec != null) {
|
||||||
|
validateTypeSpec(letDefinition.typeSpec!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateTypeSpec(typeSpec: TypeSpec) {
|
||||||
|
lookup(typeSpec.symbol) ?: throw CompileError("Unresolved type: ${typeSpec.symbol.id}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startLoop(): IrSymbol {
|
private fun startLoop(): IrSymbol {
|
||||||
@ -204,7 +220,7 @@ class AstIrEmitter(
|
|||||||
IrConditional(
|
IrConditional(
|
||||||
conditional = node.condition.visit(this),
|
conditional = node.condition.visit(this),
|
||||||
ifTrue = node.thenBlock.visit(this),
|
ifTrue = node.thenBlock.visit(this),
|
||||||
ifFalse = node.elseBlock?.visit(this) ?: IrNoneConstant
|
ifFalse = node.elseBlock?.visit(this) ?: IrNop
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun visitIndexedBy(node: IndexedBy): IrCodeElement = IrIndex(
|
override fun visitIndexedBy(node: IndexedBy): IrCodeElement = IrIndex(
|
||||||
@ -240,6 +256,9 @@ class AstIrEmitter(
|
|||||||
IrIntegerConstant(node.value)
|
IrIntegerConstant(node.value)
|
||||||
|
|
||||||
override fun visitLetAssignment(node: LetAssignment): IrCodeElement {
|
override fun visitLetAssignment(node: LetAssignment): IrCodeElement {
|
||||||
|
if (node.typeSpec != null) {
|
||||||
|
validateTypeSpec(node.typeSpec!!)
|
||||||
|
}
|
||||||
val symbol = createLocalVariable(node.symbol)
|
val symbol = createLocalVariable(node.symbol)
|
||||||
return IrDeclare(symbol, node.value.visit(this))
|
return IrDeclare(symbol, node.value.visit(this))
|
||||||
}
|
}
|
||||||
@ -295,6 +314,9 @@ class AstIrEmitter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitVarAssignment(node: VarAssignment): IrCodeElement {
|
override fun visitVarAssignment(node: VarAssignment): IrCodeElement {
|
||||||
|
if (node.typeSpec != null) {
|
||||||
|
validateTypeSpec(node.typeSpec!!)
|
||||||
|
}
|
||||||
val local = createLocalVariable(node.symbol)
|
val local = createLocalVariable(node.symbol)
|
||||||
return IrDeclare(local, node.value.visit(this))
|
return IrDeclare(local, node.value.visit(this))
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ class CompilableSymbol(val compilableSlab: CompilableSlab, val scopeSymbol: Scop
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val letDefinition = scopeSymbol.definition as LetDefinition
|
val letDefinition = scopeSymbol.definition as LetDefinition
|
||||||
|
irCodeEmitter.checkLetDefinition(letDefinition)
|
||||||
letDefinition.value
|
letDefinition.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,6 +194,8 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
|
|||||||
store(variable)
|
store(variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitIrNop(ir: IrNop) {}
|
||||||
|
|
||||||
override fun visitIrStore(ir: IrStore) {
|
override fun visitIrStore(ir: IrStore) {
|
||||||
visit(ir.value)
|
visit(ir.value)
|
||||||
val variable = code.localState.createOrFindLocal(ir.target)
|
val variable = code.localState.createOrFindLocal(ir.target)
|
||||||
|
17
examples/ack.pork
Normal file
17
examples/ack.pork
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* ackermann function */
|
||||||
|
func ack(m: int32, n: int32): int32 {
|
||||||
|
if m == 0 {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
return ack(m - 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ack(m - 1, ack(m, n - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
export func main() {
|
||||||
|
let result: int32 = ack(3, 1)
|
||||||
|
println(result)
|
||||||
|
}
|
@ -1,14 +1,7 @@
|
|||||||
import std ffi.struct
|
import std ffi.struct
|
||||||
|
|
||||||
export let timeval = ffiStructDefine(
|
export type timeval = native ffi "long" "seconds" "unsigned int" "microseconds"
|
||||||
"long", "seconds",
|
export type timezone = native ffi "int" "minutes_greenwich" "int" "dst_time"
|
||||||
"unsigned int", "microseconds"
|
|
||||||
)
|
|
||||||
|
|
||||||
export let timezone = ffiStructDefine(
|
|
||||||
"int", "minutes_greenwich",
|
|
||||||
"int", "dst_time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func gettimeofday(value, tz)
|
func gettimeofday(value, tz)
|
||||||
native ffi "c" "int gettimeofday(struct timeval*, struct timezone*)"
|
native ffi "c" "int gettimeofday(struct timeval*, struct timezone*)"
|
||||||
|
@ -8,6 +8,6 @@ func fib(n: int32): int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export func main() {
|
export func main() {
|
||||||
let result: int32 = fib(28)
|
let result: int32 = fib(31)
|
||||||
println(result)
|
println(result)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,14 @@ class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor<Unit>() {
|
|||||||
get() = symbols
|
get() = symbols
|
||||||
|
|
||||||
override fun visitFunctionDefinition(node: FunctionDefinition) {
|
override fun visitFunctionDefinition(node: FunctionDefinition) {
|
||||||
|
for (argument in node.arguments) {
|
||||||
|
visit(argument.typeSpec!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.returnType != null) {
|
||||||
|
visit(node.returnType!!)
|
||||||
|
}
|
||||||
|
|
||||||
internalSymbols.add(node.arguments.map { it.symbol }.toMutableSet())
|
internalSymbols.add(node.arguments.map { it.symbol }.toMutableSet())
|
||||||
node.block?.visit(this)
|
node.block?.visit(this)
|
||||||
internalSymbols.removeLast()
|
internalSymbols.removeLast()
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
export type int32 = native internal "int32"
|
export type int32 = native internal "int32"
|
||||||
export type int64 = native internal "int64"
|
export type int64 = native internal "int64"
|
||||||
|
export type float32 = native internal "float32"
|
||||||
|
export type float64 = native internal "float64"
|
||||||
export type string = native internal "string"
|
export type string = native internal "string"
|
||||||
export type list = native internal "list"
|
export type list = native internal "list"
|
||||||
|
export type bool = native internal "bool"
|
||||||
export type any = native internal "any"
|
export type any = native internal "any"
|
||||||
|
|
||||||
export func print(values...: string)
|
export func print(values...: string)
|
||||||
|
@ -69,7 +69,7 @@ class CompileCommand : CliktCommand("compile") {
|
|||||||
annotation = " ; ${annotations.joinToString(", ") { it.text }}"
|
annotation = " ; ${annotations.joinToString(", ") { it.text }}"
|
||||||
}
|
}
|
||||||
print(" ${symbol.offset + index.toUInt()} ${op}${annotation}")
|
print(" ${symbol.offset + index.toUInt()} ${op}${annotation}")
|
||||||
if (op.code == Opcode.Constant || op.code == Opcode.NativeFunction) {
|
if (op.code == Opcode.Constant || op.code == Opcode.NativeFunction || op.code == Opcode.NativeType) {
|
||||||
val constant = compiledWorld.constantPool.constants[op.args[0].toInt()]
|
val constant = compiledWorld.constantPool.constants[op.args[0].toInt()]
|
||||||
val constantString = when (constant.tag) {
|
val constantString = when (constant.tag) {
|
||||||
ConstantTag.String -> "string = \"" + constant.readAsString() + "\""
|
ConstantTag.String -> "string = \"" + constant.readAsString() + "\""
|
||||||
|
Loading…
Reference in New Issue
Block a user