mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
fix RPN comparison exprs
This commit is contained in:
parent
374464a1f8
commit
df2d7d4734
@ -6,7 +6,7 @@ import prog8.code.core.*
|
||||
* Produces readable text from a [PtNode] (AST node, usually starting with PtProgram as root),
|
||||
* passing it as a String to the specified receiver function.
|
||||
*/
|
||||
fun printAst(root: PtNode, output: (text: String) -> Unit) {
|
||||
fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Unit) {
|
||||
fun type(dt: DataType) = "!${dt.name.lowercase()}!"
|
||||
fun txt(node: PtNode): String {
|
||||
return when(node) {
|
||||
@ -136,16 +136,22 @@ fun printAst(root: PtNode, output: (text: String) -> Unit) {
|
||||
root.children.forEach {
|
||||
walkAst(it) { node, depth ->
|
||||
val txt = txt(node)
|
||||
if(txt.isNotEmpty())
|
||||
output(" ".repeat(depth) + txt(node))
|
||||
val library = if(node is PtBlock) node.library else node.definingBlock()?.library==true
|
||||
if(!library || !skipLibraries) {
|
||||
if (txt.isNotEmpty())
|
||||
output(" ".repeat(depth) + txt(node))
|
||||
}
|
||||
}
|
||||
}
|
||||
println()
|
||||
} else {
|
||||
walkAst(root) { node, depth ->
|
||||
val txt = txt(node)
|
||||
if(txt.isNotEmpty())
|
||||
output(" ".repeat(depth) + txt(node))
|
||||
val library = if(node is PtBlock) node.library else node.definingBlock()?.library==true
|
||||
if(!library || !skipLibraries) {
|
||||
if (txt.isNotEmpty())
|
||||
output(" ".repeat(depth) + txt(node))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ class AsmGen6502: ICodeGeneratorBackend {
|
||||
errors.warn("EXPERIMENTAL RPN EXPRESSION NODES ARE USED. CODE SIZE+SPEED WILL SUFFER.", Position.DUMMY)
|
||||
}
|
||||
|
||||
// printAst(program, true) { println(it) }
|
||||
|
||||
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
|
||||
return asmgen.compileToAssembly()
|
||||
}
|
||||
|
@ -102,6 +102,28 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
||||
RegisterOrPair.R15 -> AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, if(signed) DataType.WORD else DataType.UWORD, scope, pos, register = registers)
|
||||
}
|
||||
}
|
||||
|
||||
fun isSameAs(left: PtExpression): Boolean =
|
||||
when(kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
val scopedName: String = if('.' in asmVarname)
|
||||
asmVarname
|
||||
else {
|
||||
val scopeName = (scope as? PtNamedNode)?.scopedName
|
||||
if (scopeName == null) asmVarname else "$scopeName.$asmVarname"
|
||||
}
|
||||
left is PtIdentifier && left.name==scopedName
|
||||
}
|
||||
TargetStorageKind.ARRAY -> {
|
||||
left is PtArrayIndexer && left isSameAs array!!
|
||||
}
|
||||
TargetStorageKind.MEMORY -> {
|
||||
left isSameAs memory!!
|
||||
}
|
||||
TargetStorageKind.REGISTER, TargetStorageKind.STACK -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||
|
@ -366,7 +366,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
val value = assign.source.expression as PtRpn
|
||||
val (left, oper, right) = value.finalOperation()
|
||||
|
||||
// TODO RPN the fallthrough if size>3 seems to generate not 100% correct code... (balls example fills the screen weird)
|
||||
// TODO RPN the fallthrough if size>3 seems to generate very inefficient code...
|
||||
if(value.children.size==3 && oper.operator in ComparisonOperators) {
|
||||
assignRPNComparison(assign, value)
|
||||
return true
|
||||
@ -564,20 +564,46 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
val rightNum = right as? PtNumber
|
||||
val jumpIfFalseLabel = asmgen.makeLabel("cmp")
|
||||
|
||||
when(assign.target.datatype) {
|
||||
in ByteDatatypes -> assignConstantByte(assign.target, 0)
|
||||
in WordDatatypes -> assignConstantWord(assign.target, 0)
|
||||
DataType.FLOAT -> assignConstantFloat(assign.target, 0.0)
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
if(assign.target.isSameAs(left)) {
|
||||
// In-place comparison Target = Target <compare> Right
|
||||
// NOTE : this generates pretty inefficient code.... TODO RPN optimize?
|
||||
val targetDt = assign.target.datatype
|
||||
val tempVar = asmgen.getTempVarName(assign.target.datatype)
|
||||
val tempTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, targetDt, comparison.definingISub(), comparison.position, variableAsmName = tempVar)
|
||||
when (assign.target.datatype) {
|
||||
in ByteDatatypes -> assignConstantByte(tempTarget, 0)
|
||||
in WordDatatypes -> assignConstantWord(tempTarget, 0)
|
||||
DataType.FLOAT -> assignConstantFloat(tempTarget, 0.0)
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
asmgen.testNonzeroComparisonAndJump(left, oper.operator, right, jumpIfFalseLabel, leftNum, rightNum)
|
||||
when (assign.target.datatype) {
|
||||
in ByteDatatypes -> assignConstantByte(tempTarget, 1)
|
||||
in WordDatatypes -> assignConstantWord(tempTarget, 1)
|
||||
DataType.FLOAT -> assignConstantFloat(tempTarget, 1.0)
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
asmgen.out(jumpIfFalseLabel)
|
||||
val tempLeft = PtIdentifier(tempVar, targetDt, comparison.position)
|
||||
tempLeft.parent=comparison
|
||||
asmgen.assignExpressionTo(tempLeft, assign.target)
|
||||
} else {
|
||||
// Normal comparison Target = Left <compare> Right
|
||||
when (assign.target.datatype) {
|
||||
in ByteDatatypes -> assignConstantByte(assign.target, 0)
|
||||
in WordDatatypes -> assignConstantWord(assign.target, 0)
|
||||
DataType.FLOAT -> assignConstantFloat(assign.target, 0.0)
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
asmgen.testNonzeroComparisonAndJump(left, oper.operator, right, jumpIfFalseLabel, leftNum, rightNum)
|
||||
when (assign.target.datatype) {
|
||||
in ByteDatatypes -> assignConstantByte(assign.target, 1)
|
||||
in WordDatatypes -> assignConstantWord(assign.target, 1)
|
||||
DataType.FLOAT -> assignConstantFloat(assign.target, 1.0)
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
asmgen.out(jumpIfFalseLabel)
|
||||
}
|
||||
asmgen.testNonzeroComparisonAndJump(left, oper.operator, right, jumpIfFalseLabel, leftNum, rightNum)
|
||||
when(assign.target.datatype) {
|
||||
in ByteDatatypes -> assignConstantByte(assign.target, 1)
|
||||
in WordDatatypes -> assignConstantWord(assign.target, 1)
|
||||
DataType.FLOAT -> assignConstantFloat(assign.target, 1.0)
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
asmgen.out(jumpIfFalseLabel)
|
||||
}
|
||||
|
||||
private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
|
@ -120,7 +120,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||
// println("*********** COMPILER AST RIGHT BEFORE ASM GENERATION *************")
|
||||
// printProgram(program)
|
||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||
// printAst(intermediateAst, ::println)
|
||||
// printAst(intermediateAst, true, ::println)
|
||||
|
||||
if(!createAssemblyAndAssemble(intermediateAst, args.errors, compilationOptions)) {
|
||||
System.err.println("Error in codegeneration or assembler")
|
||||
|
@ -66,7 +66,7 @@ class TestIntermediateAst: FunSpec({
|
||||
val fcall = (entry.children[4] as PtAssignment).value as PtFunctionCall
|
||||
fcall.void shouldBe false
|
||||
fcall.type shouldBe DataType.UBYTE
|
||||
printAst(ast, ::println)
|
||||
printAst(ast, false, ::println)
|
||||
}
|
||||
|
||||
})
|
@ -1,7 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
BRANCH: balls.p8 directions are wrong since the comparison operator fallthrough in attemptAssignOptimizedExprRPN
|
||||
BRANCH: Fix the TODO RPN routines to be optimized assembly in RpnExpressionAsmGen.kt
|
||||
BRANCH: check BinExprSplitter disablement any effect for RPN?
|
||||
BRANCH: Implement RPN codegen for IR.
|
||||
|
@ -43,7 +43,7 @@ main {
|
||||
DX[lp] = true
|
||||
else
|
||||
BX[lp]=BX[lp]-1
|
||||
} else if DX[lp] {
|
||||
} else {
|
||||
if (BX[lp] == txt.DEFAULT_WIDTH-1) {
|
||||
BX[lp] = txt.DEFAULT_WIDTH-2
|
||||
DX[lp] = false
|
||||
@ -56,7 +56,7 @@ main {
|
||||
DY[lp] = true
|
||||
else
|
||||
BY[lp]=BY[lp]-1
|
||||
} else if DY[lp] == 1 {
|
||||
} else {
|
||||
if (BY[lp] == txt.DEFAULT_HEIGHT-1) {
|
||||
BY[lp] = txt.DEFAULT_HEIGHT-2
|
||||
DY[lp] = false
|
||||
|
@ -1,4 +1,5 @@
|
||||
%import math
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
@ -6,15 +7,15 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
; ubyte[255] BC
|
||||
; bool[255] DX
|
||||
|
||||
if math.rnd() & 22 {
|
||||
cx16.r0L++
|
||||
bool x
|
||||
ubyte y
|
||||
repeat 20 {
|
||||
x = math.rnd() & 1
|
||||
y = ((math.rnd()&1)!=0)
|
||||
txt.print_ub(x)
|
||||
txt.spc()
|
||||
txt.print_ub(y)
|
||||
txt.nl()
|
||||
}
|
||||
; BC[2] = math.rnd() & 15
|
||||
; BC[3] = math.rnd() & 15
|
||||
; BC[4] = math.rnd() & 15
|
||||
;DX[2] = math.rnd() & 1
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user