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 visitIrListSize(ir: IrListSize): T
|
||||
fun visitIrDeclare(ir: IrDeclare): T
|
||||
fun visitIrNop(ir: IrNop): T
|
||||
|
||||
fun visit(ir: IrElement): T = when (ir) {
|
||||
is IrBreak -> visitIrBeak(ir)
|
||||
@ -61,5 +62,6 @@ interface IrVisitor<T> {
|
||||
is IrIndex -> visitIrIndex(ir)
|
||||
is IrListSize -> visitIrListSize(ir)
|
||||
is IrDeclare -> visitIrDeclare(ir)
|
||||
IrNop -> visitIrNop(ir as IrNop)
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,26 @@ class AstIrEmitter(
|
||||
fun createFunctionArguments(functionDefinition: FunctionDefinition) {
|
||||
val functionSymbols = mutableListOf<IrFunctionArgument>()
|
||||
for (arg in functionDefinition.arguments) {
|
||||
if (arg.typeSpec != null) {
|
||||
validateTypeSpec(arg.typeSpec!!)
|
||||
}
|
||||
val symbol = createLocalVariable(arg.symbol)
|
||||
functionSymbols.add(IrFunctionArgument(symbol))
|
||||
}
|
||||
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 {
|
||||
@ -204,7 +220,7 @@ class AstIrEmitter(
|
||||
IrConditional(
|
||||
conditional = node.condition.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(
|
||||
@ -240,6 +256,9 @@ class AstIrEmitter(
|
||||
IrIntegerConstant(node.value)
|
||||
|
||||
override fun visitLetAssignment(node: LetAssignment): IrCodeElement {
|
||||
if (node.typeSpec != null) {
|
||||
validateTypeSpec(node.typeSpec!!)
|
||||
}
|
||||
val symbol = createLocalVariable(node.symbol)
|
||||
return IrDeclare(symbol, node.value.visit(this))
|
||||
}
|
||||
@ -295,6 +314,9 @@ class AstIrEmitter(
|
||||
}
|
||||
|
||||
override fun visitVarAssignment(node: VarAssignment): IrCodeElement {
|
||||
if (node.typeSpec != null) {
|
||||
validateTypeSpec(node.typeSpec!!)
|
||||
}
|
||||
val local = createLocalVariable(node.symbol)
|
||||
return IrDeclare(local, node.value.visit(this))
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ class CompilableSymbol(val compilableSlab: CompilableSlab, val scopeSymbol: Scop
|
||||
|
||||
else -> {
|
||||
val letDefinition = scopeSymbol.definition as LetDefinition
|
||||
irCodeEmitter.checkLetDefinition(letDefinition)
|
||||
letDefinition.value
|
||||
}
|
||||
}
|
||||
|
@ -194,6 +194,8 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
|
||||
store(variable)
|
||||
}
|
||||
|
||||
override fun visitIrNop(ir: IrNop) {}
|
||||
|
||||
override fun visitIrStore(ir: IrStore) {
|
||||
visit(ir.value)
|
||||
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
|
||||
|
||||
export let timeval = ffiStructDefine(
|
||||
"long", "seconds",
|
||||
"unsigned int", "microseconds"
|
||||
)
|
||||
|
||||
export let timezone = ffiStructDefine(
|
||||
"int", "minutes_greenwich",
|
||||
"int", "dst_time"
|
||||
)
|
||||
export type timeval = native ffi "long" "seconds" "unsigned int" "microseconds"
|
||||
export type timezone = native ffi "int" "minutes_greenwich" "int" "dst_time"
|
||||
|
||||
func gettimeofday(value, tz)
|
||||
native ffi "c" "int gettimeofday(struct timeval*, struct timezone*)"
|
||||
|
@ -8,6 +8,6 @@ func fib(n: int32): int32 {
|
||||
}
|
||||
|
||||
export func main() {
|
||||
let result: int32 = fib(28)
|
||||
let result: int32 = fib(31)
|
||||
println(result)
|
||||
}
|
||||
|
@ -11,6 +11,14 @@ class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor<Unit>() {
|
||||
get() = symbols
|
||||
|
||||
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())
|
||||
node.block?.visit(this)
|
||||
internalSymbols.removeLast()
|
||||
|
@ -1,7 +1,10 @@
|
||||
export type int32 = native internal "int32"
|
||||
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 list = native internal "list"
|
||||
export type bool = native internal "bool"
|
||||
export type any = native internal "any"
|
||||
|
||||
export func print(values...: string)
|
||||
|
@ -69,7 +69,7 @@ class CompileCommand : CliktCommand("compile") {
|
||||
annotation = " ; ${annotations.joinToString(", ") { it.text }}"
|
||||
}
|
||||
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 constantString = when (constant.tag) {
|
||||
ConstantTag.String -> "string = \"" + constant.readAsString() + "\""
|
||||
|
Loading…
Reference in New Issue
Block a user