mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 04:31:20 +00:00
tweak & fix if expression with word condition
This commit is contained in:
parent
3b798097b9
commit
7cfb33a448
@ -43,12 +43,16 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
|
||||
val prefixCond = stmt.condition as? PtPrefix
|
||||
if(prefixCond?.operator=="not") {
|
||||
checkNotRomsubReturnsStatusReg(prefixCond.value)
|
||||
assignConditionValueToRegisterAndTest(prefixCond.value)
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bne", stmt)
|
||||
if(stmt.hasElse())
|
||||
throw AssemblyError("not prefix in ifelse should have been replaced by swapped if-else blocks")
|
||||
else {
|
||||
checkNotRomsubReturnsStatusReg(prefixCond.value)
|
||||
assignConditionValueToRegisterAndTest(prefixCond.value)
|
||||
return if (jumpAfterIf != null)
|
||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bne", stmt)
|
||||
}
|
||||
}
|
||||
|
||||
throw AssemblyError("weird non-boolean condition node type ${stmt.condition} at ${stmt.condition.position}")
|
||||
@ -99,8 +103,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
else if(condition is PtPrefix && condition.operator=="not") {
|
||||
assignConditionValueToRegisterAndTest(condition.value)
|
||||
asmgen.out(" bne $falseLabel")
|
||||
throw AssemblyError("not prefix in ifexpression should have been replaced by swapped values")
|
||||
} else {
|
||||
// 'simple' condition, check if it is a byte bittest
|
||||
val bittest = condition as? PtBuiltinFunctionCall
|
||||
@ -396,51 +399,27 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun translateIfWordConditionBranch(condition: PtBinaryExpression, falseLabel: String) {
|
||||
val signed = condition.left.type in SignedDatatypes
|
||||
// TODO can we reuse this whole thing from IfElse ?
|
||||
val constValue = condition.right.asConstInteger()
|
||||
if(constValue==0) {
|
||||
|
||||
// TODO reuse more code from regular if statements. Need a shared routine like isWordExprZero() ?
|
||||
when(condition.operator) {
|
||||
"==" -> {
|
||||
// if w==0
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.AY, signed)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG | bne $falseLabel")
|
||||
return
|
||||
if(constValue!=null) {
|
||||
if (constValue == 0) {
|
||||
when (condition.operator) {
|
||||
"==" -> return translateWordExprIsZero(condition.left, falseLabel)
|
||||
"!=" -> return translateWordExprIsNotZero(condition.left, falseLabel)
|
||||
}
|
||||
"!=" -> {
|
||||
// if w!=0
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.AY, signed)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG | beq $falseLabel")
|
||||
return
|
||||
}
|
||||
if (constValue != 0) {
|
||||
when (condition.operator) {
|
||||
"==" -> return translateWordExprEqualsNumber(condition.left, constValue, falseLabel)
|
||||
"!=" -> return translateWordExprNotEqualsNumber(condition.left, constValue, falseLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(constValue!=0) {
|
||||
// TODO reuse more code from regular if statements. Need a shared routine like isWordExprEqualNumber() ?
|
||||
when(condition.operator) {
|
||||
"==" -> {
|
||||
// if w==number
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.AY, signed)
|
||||
asmgen.out("""
|
||||
cmp #<$constValue
|
||||
bne $falseLabel
|
||||
cpy #>$constValue
|
||||
bne $falseLabel""")
|
||||
return
|
||||
}
|
||||
"!=" -> {
|
||||
// if w!=number
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.AY, signed)
|
||||
asmgen.out("""
|
||||
cmp #<$constValue
|
||||
bne +
|
||||
cpy #>$constValue
|
||||
beq $falseLabel
|
||||
+""")
|
||||
return
|
||||
}
|
||||
val variable = condition.right as? PtIdentifier
|
||||
if(variable!=null) {
|
||||
when (condition.operator) {
|
||||
"==" -> return translateWordExprEqualsVariable(condition.left, variable, falseLabel)
|
||||
"!=" -> return translateWordExprNotEqualsVariable(condition.left, variable, falseLabel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,6 +428,130 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
asmgen.out(" beq $falseLabel")
|
||||
}
|
||||
|
||||
private fun translateWordExprNotEqualsVariable(expr: PtExpression, variable: PtIdentifier, falseLabel: String) {
|
||||
// if w!=variable
|
||||
// TODO reuse code from ifElse?
|
||||
val varRight = asmgen.asmVariableName(variable)
|
||||
if(expr is PtIdentifier) {
|
||||
val varLeft = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
lda $varLeft
|
||||
cmp $varRight
|
||||
bne +
|
||||
lda $varLeft+1
|
||||
cmp $varRight+1
|
||||
beq $falseLabel
|
||||
+""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(expr, RegisterOrPair.AY, false)
|
||||
asmgen.out("""
|
||||
cmp $varRight
|
||||
bne +
|
||||
cpy $varRight+1
|
||||
beq $falseLabel
|
||||
+""")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateWordExprEqualsVariable(expr: PtExpression, variable: PtIdentifier, falseLabel: String) {
|
||||
// if w==variable
|
||||
// TODO reuse code from ifElse?
|
||||
val varRight = asmgen.asmVariableName(variable)
|
||||
if(expr is PtIdentifier) {
|
||||
val varLeft = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
lda $varLeft
|
||||
cmp $varRight
|
||||
bne $falseLabel
|
||||
lda $varLeft+1
|
||||
cmp $varRight+1
|
||||
bne $falseLabel""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(expr, RegisterOrPair.AY, false)
|
||||
asmgen.out("""
|
||||
cmp $varRight
|
||||
bne $falseLabel
|
||||
cpy $varRight+1
|
||||
bne $falseLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateWordExprNotEqualsNumber(expr: PtExpression, number: Int, falseLabel: String) {
|
||||
// if w!=number
|
||||
// TODO reuse code from ifElse?
|
||||
if(expr is PtIdentifier) {
|
||||
val varname = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
lda $varname
|
||||
cmp #<$number
|
||||
bne +
|
||||
lda $varname+1
|
||||
cmp #>$number
|
||||
beq $falseLabel
|
||||
+""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(expr, RegisterOrPair.AY, false)
|
||||
asmgen.out("""
|
||||
cmp #<$number
|
||||
bne +
|
||||
cpy #>$number
|
||||
beq $falseLabel
|
||||
+""")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateWordExprEqualsNumber(expr: PtExpression, number: Int, falseLabel: String) {
|
||||
// if w==number
|
||||
// TODO reuse code from ifElse?
|
||||
if(expr is PtIdentifier) {
|
||||
val varname = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
lda $varname
|
||||
cmp #<$number
|
||||
bne $falseLabel
|
||||
lda $varname+1
|
||||
cmp #>$number
|
||||
bne $falseLabel""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(expr, RegisterOrPair.AY, false)
|
||||
asmgen.out( """
|
||||
cmp #<$number
|
||||
bne $falseLabel
|
||||
cpy #>$number
|
||||
bne $falseLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateWordExprIsNotZero(expr: PtExpression, falseLabel: String) {
|
||||
// if w!=0
|
||||
// TODO reuse code from ifElse?
|
||||
if(expr is PtIdentifier) {
|
||||
val varname = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
lda $varname
|
||||
ora $varname+1
|
||||
beq $falseLabel""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(expr, RegisterOrPair.AY, false)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG | beq $falseLabel")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateWordExprIsZero(expr: PtExpression, falseLabel: String) {
|
||||
// if w==0
|
||||
// TODO reuse code from ifElse?
|
||||
if(expr is PtIdentifier) {
|
||||
val varname = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
lda $varname
|
||||
ora $varname+1
|
||||
bne $falseLabel""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(expr, RegisterOrPair.AY, false)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG | bne $falseLabel")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateIfCompareWithZeroByteBranch(condition: PtBinaryExpression, signed: Boolean, falseLabel: String) {
|
||||
// optimized code for byte comparisons with 0
|
||||
assignConditionValueToRegisterAndTest(condition.left)
|
||||
|
@ -91,6 +91,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
|
||||
private fun translate(ifExpr: PtIfExpression): ExpressionCodeResult {
|
||||
|
||||
if((ifExpr.condition as? PtPrefix)?.operator=="not")
|
||||
throw AssemblyError("not prefix in ifexpression should have been replaced by swapped values")
|
||||
|
||||
// TODO don't store condition as expression result but just use the flags, like a normal PtIfElse translation does
|
||||
val condTr = translateExpression(ifExpr.condition)
|
||||
val trueTr = translateExpression(ifExpr.truevalue)
|
||||
|
@ -1330,6 +1330,9 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
private fun translateIfElse(ifElse: PtIfElse): IRCodeChunks {
|
||||
if((ifElse.condition as? PtPrefix)?.operator=="not")
|
||||
throw AssemblyError("not prefix in ifelse should have been replaced by swapped if-else blocks")
|
||||
|
||||
val condition = ifElse.condition as? PtBinaryExpression
|
||||
if(condition==null || condition.left.type != DataType.FLOAT) {
|
||||
return ifWithElse_IntegerCond(ifElse)
|
||||
|
@ -238,11 +238,8 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
if(expr.operator=="==") {
|
||||
if(rightDt==DataType.BOOL && leftDt==DataType.BOOL) {
|
||||
val rightConstBool = rightVal?.asBooleanValue
|
||||
if(rightConstBool!=null) {
|
||||
return if(rightConstBool)
|
||||
listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
else
|
||||
listOf(IAstModification.ReplaceNode(expr, PrefixExpression("not", expr.left, expr.position), parent))
|
||||
if(rightConstBool==true) {
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
}
|
||||
}
|
||||
if (rightVal?.number == 1.0) {
|
||||
@ -261,11 +258,8 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
if (expr.operator=="!=") {
|
||||
if(rightDt==DataType.BOOL && leftDt==DataType.BOOL) {
|
||||
val rightConstBool = rightVal?.asBooleanValue
|
||||
if(rightConstBool!=null) {
|
||||
return if (rightConstBool)
|
||||
listOf(IAstModification.ReplaceNode(expr, PrefixExpression("not", expr.left, expr.position), parent))
|
||||
else
|
||||
listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
if(rightConstBool==false) {
|
||||
listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
}
|
||||
}
|
||||
if (rightVal?.number == 1.0) {
|
||||
@ -416,21 +410,6 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(expr.operator=="not") {
|
||||
// not X <compare> Y -> X <invertedcompare> Y
|
||||
val binExpr = expr.expression as? BinaryExpression
|
||||
if(binExpr!=null) {
|
||||
val invertedOperator = invertedComparisonOperator(binExpr.operator)
|
||||
if(invertedOperator!=null) {
|
||||
val inverted = BinaryExpression(binExpr.left, invertedOperator, binExpr.right, binExpr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, inverted, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
private fun applyAbsorptionLaws(expr: BinaryExpression): Expression? {
|
||||
// NOTE: only when the terms are not function calls!!!
|
||||
if(expr.left is IFunctionCall || expr.right is IFunctionCall)
|
||||
|
@ -127,19 +127,6 @@ class StatementOptimizer(private val program: Program,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// switch if/else around if the condition is a not
|
||||
val prefixCond = ifElse.condition as? PrefixExpression
|
||||
if(prefixCond?.operator=="not") {
|
||||
errors.info("invert conditon and swap if/else blocks", ifElse.condition.position)
|
||||
val newTruePart = AnonymousScope(ifElse.elsepart.statements, ifElse.elsepart.position)
|
||||
val newElsePart = AnonymousScope(ifElse.truepart.statements, ifElse.truepart.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(ifElse.elsepart, newElsePart, ifElse),
|
||||
IAstModification.ReplaceNode(ifElse.truepart, newTruePart, ifElse),
|
||||
IAstModification.ReplaceNode(ifElse.condition, prefixCond.expression, ifElse)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
|
@ -3,10 +3,8 @@ package prog8.compiler.astprocessing
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.expressions.invertCondition
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.IfElse
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
@ -97,7 +95,6 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val
|
||||
|
||||
override fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(expr.operator == "not") {
|
||||
|
||||
// first check if we're already part of a "boolean" expression (i.e. comparing against 0 or 1)
|
||||
// if so, simplify THAT whole expression rather than making it more complicated
|
||||
if (parent is BinaryExpression) {
|
||||
@ -155,22 +152,49 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val
|
||||
val notZero = BinaryExpression(x, "!=", NumericLiteral(dt, 0.0, expr.position), expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, notZero, parent))
|
||||
}
|
||||
|
||||
// not X <compare> Y -> X <invertedcompare> Y
|
||||
val subBinExpr = expr.expression as? BinaryExpression
|
||||
if(subBinExpr?.operator=="==") {
|
||||
if(subBinExpr.right.constValue(program)?.number==0.0) {
|
||||
// not(x==0) -> x!=0
|
||||
subBinExpr.operator = "!="
|
||||
return listOf(IAstModification.ReplaceNode(expr, subBinExpr, parent))
|
||||
}
|
||||
} else if(subBinExpr?.operator=="!=") {
|
||||
if(subBinExpr.right.constValue(program)?.number==0.0) {
|
||||
// not(x!=0) -> x==0
|
||||
subBinExpr.operator = "=="
|
||||
return listOf(IAstModification.ReplaceNode(expr, subBinExpr, parent))
|
||||
if(subBinExpr!=null) {
|
||||
val invertedOperator = invertedComparisonOperator(subBinExpr.operator)
|
||||
if(invertedOperator!=null) {
|
||||
val inverted = BinaryExpression(subBinExpr.left, invertedOperator, subBinExpr.right, subBinExpr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, inverted, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(ifElse: IfElse, parent: Node): Iterable<IAstModification> {
|
||||
if(ifElse.elsepart.isNotEmpty()) {
|
||||
val prefix = ifElse.condition as? PrefixExpression
|
||||
if(prefix?.operator=="not") {
|
||||
// if not x a else b -> if x b else a
|
||||
errors.info("invert condition and swap if/else blocks", ifElse.condition.position)
|
||||
ifElse.condition = prefix.expression
|
||||
ifElse.condition.parent = ifElse
|
||||
val elsepart = ifElse.elsepart
|
||||
ifElse.elsepart = ifElse.truepart
|
||||
ifElse.truepart = elsepart
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(ifExpr: IfExpression, parent: Node): Iterable<IAstModification> {
|
||||
val prefix = ifExpr.condition as? PrefixExpression
|
||||
if(prefix?.operator=="not") {
|
||||
// if not x a else b -> if x b else a
|
||||
errors.info("invert condition and swap values", ifExpr.condition.position)
|
||||
ifExpr.condition = prefix.expression
|
||||
ifExpr.condition.parent = ifExpr
|
||||
val falsevalue = ifExpr.falsevalue
|
||||
ifExpr.falsevalue = ifExpr.truevalue
|
||||
ifExpr.truevalue = falsevalue
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,66 @@
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
%memtop $0840
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
cx16.r0L=0
|
||||
if cx16.r0L==0 {
|
||||
uword[] addresses = [scores2, start]
|
||||
uword[] @split scores1 = [10, 25, 50, 100] ; can never clear more than 4 lines at once
|
||||
uword[] @split scores2 = [10, 25, 50, 100] ; can never clear more than 4 lines at once
|
||||
cx16.r0=0
|
||||
|
||||
cx16.r0 = &scores1
|
||||
cx16.r1 = &scores2
|
||||
cx16.r2 = &addresses
|
||||
}
|
||||
if cx16.r0==0
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0==0 42 else 99
|
||||
|
||||
if cx16.r0==33
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0==33 42 else 99
|
||||
|
||||
if cx16.r0!=3333
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=3333 42 else 99
|
||||
|
||||
if cx16.r0!=0
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=0 42 else 99
|
||||
|
||||
if cx16.r0!=33
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=0 42 else 99
|
||||
|
||||
if cx16.r0==cx16.r9
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0==cx16.r9 42 else 99
|
||||
|
||||
if cx16.r0!=cx16.r9
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0!=cx16.r9 42 else 99
|
||||
|
||||
if cx16.r0>cx16.r1
|
||||
cx16.r1L=42
|
||||
else
|
||||
cx16.r1L=99
|
||||
|
||||
cx16.r2L = if cx16.r0>cx16.r1 42 else 99
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user