mirror of
https://github.com/irmen/prog8.git
synced 2025-01-05 03:31:09 +00:00
keep distinction between logical and bitwise boolean operators
This commit is contained in:
parent
f790182f0b
commit
8f18b5b8a7
codeGenCpu6502/src/prog8/codegen/cpu6502/assignment
codeGenIntermediate/src/prog8/codegen/intermediate
compiler
docs/source
examples
@ -49,54 +49,24 @@ internal class AnyExprAsmGen(
|
||||
|
||||
private fun assignWordBinExpr(expr: PtBinaryExpression): Boolean {
|
||||
when(expr.operator) {
|
||||
"+" -> {
|
||||
TODO("word + at ${expr.position}")
|
||||
}
|
||||
"-" -> {
|
||||
TODO("word - at ${expr.position}")
|
||||
}
|
||||
"*" -> {
|
||||
TODO("word * at ${expr.position}")
|
||||
}
|
||||
"/" -> {
|
||||
TODO("word / at ${expr.position}")
|
||||
}
|
||||
"<<" -> {
|
||||
TODO("word << at ${expr.position}")
|
||||
}
|
||||
">>" -> {
|
||||
TODO("word >> at ${expr.position}")
|
||||
}
|
||||
"%" -> {
|
||||
TODO("word % at ${expr.position}")
|
||||
}
|
||||
"&", "and" -> {
|
||||
TODO("word and at ${expr.position}")
|
||||
}
|
||||
"|", "or" -> {
|
||||
TODO("word or at ${expr.position}")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
TODO("word xor at ${expr.position}")
|
||||
}
|
||||
"==" -> {
|
||||
TODO("word == at ${expr.position}")
|
||||
}
|
||||
"!=" -> {
|
||||
TODO("word != at ${expr.position}")
|
||||
}
|
||||
"<" -> {
|
||||
TODO("word < at ${expr.position}")
|
||||
}
|
||||
"<=" -> {
|
||||
TODO("word <= at ${expr.position}")
|
||||
}
|
||||
">" -> {
|
||||
TODO("word > at ${expr.position}")
|
||||
}
|
||||
">=" -> {
|
||||
TODO("word >= at ${expr.position}")
|
||||
}
|
||||
"+" -> TODO("word + at ${expr.position}")
|
||||
"-" -> TODO("word - at ${expr.position}")
|
||||
"*" -> TODO("word * at ${expr.position}")
|
||||
"/" -> TODO("word / at ${expr.position}")
|
||||
"<<" -> TODO("word << at ${expr.position}")
|
||||
">>" -> TODO("word >> at ${expr.position}")
|
||||
"%" -> TODO("word % at ${expr.position}")
|
||||
"and" -> TODO("word logical and (with optional shortcircuit) ${expr.position}")
|
||||
"or" -> TODO("word logical or (with optional shortcircuit) ${expr.position}")
|
||||
"&" -> TODO("word and at ${expr.position}")
|
||||
"|" -> TODO("word or at ${expr.position}")
|
||||
"^", "xor" -> TODO("word xor at ${expr.position}")
|
||||
"==" -> TODO("word == at ${expr.position}")
|
||||
"!=" -> TODO("word != at ${expr.position}")
|
||||
"<" -> TODO("word < at ${expr.position}")
|
||||
"<=" -> TODO("word <= at ${expr.position}")
|
||||
">" -> TODO("word > at ${expr.position}")
|
||||
">=" -> TODO("word >= at ${expr.position}")
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
@ -134,7 +104,9 @@ internal class AnyExprAsmGen(
|
||||
"%" -> {
|
||||
TODO("byte % at ${expr.position}")
|
||||
}
|
||||
"&", "and" -> {
|
||||
"and" -> TODO("logical and (with optional shortcircuit) ${expr.position}")
|
||||
"or" -> TODO("logical or (with optional shortcircuit) ${expr.position}")
|
||||
"&" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
@ -142,7 +114,7 @@ internal class AnyExprAsmGen(
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
|
@ -427,7 +427,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
val translatedOk = when (expr.operator) {
|
||||
in ComparisonOperators -> optimizedComparison(expr, assign)
|
||||
in setOf("&", "|", "^", "and", "or", "xor") -> optimizedLogicalOrBitwiseExpr(expr, assign.target)
|
||||
in setOf("&", "|", "^", "xor") -> optimizedBitwiseExpr(expr, assign.target)
|
||||
in setOf("and", "or") -> optimizedLogicalAndOrExpr(expr, assign.target)
|
||||
"+", "-" -> optimizedPlusMinExpr(expr, assign.target)
|
||||
"<<", ">>" -> optimizedBitshiftExpr(expr, assign.target)
|
||||
"*" -> optimizedMultiplyExpr(expr, assign.target)
|
||||
@ -988,15 +989,15 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
return false
|
||||
}
|
||||
|
||||
private fun optimizedLogicalOrBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
private fun optimizedBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
||||
if (expr.right.isSimple()) {
|
||||
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
||||
assignLogicalWithSimpleRightOperandByte(target, expr.left, expr.operator, expr.right)
|
||||
assignBitwiseWithSimpleRightOperandByte(target, expr.left, expr.operator, expr.right)
|
||||
return true
|
||||
}
|
||||
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
||||
assignLogicalWithSimpleRightOperandByte(target, expr.right, expr.operator, expr.left)
|
||||
assignBitwiseWithSimpleRightOperandByte(target, expr.right, expr.operator, expr.left)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1006,10 +1007,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
when (expr.operator) {
|
||||
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
"&" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"|" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
else -> throw AssemblyError("invalid bitwise operator")
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||
return true
|
||||
@ -1017,20 +1018,68 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
else if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||
if (expr.right.isSimple()) {
|
||||
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
||||
assignLogicalWithSimpleRightOperandWord(target, expr.left, expr.operator, expr.right)
|
||||
assignBitwiseWithSimpleRightOperandWord(target, expr.left, expr.operator, expr.right)
|
||||
return true
|
||||
}
|
||||
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
||||
assignLogicalWithSimpleRightOperandWord(target, expr.right, expr.operator, expr.left)
|
||||
assignBitwiseWithSimpleRightOperandWord(target, expr.right, expr.operator, expr.left)
|
||||
return true
|
||||
}
|
||||
}
|
||||
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
||||
when (expr.operator) {
|
||||
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_W1 | tax | tya | and P8ZP_SCRATCH_W1+1 | tay | txa")
|
||||
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_W1 | tax | tya | ora P8ZP_SCRATCH_W1+1 | tay | txa")
|
||||
"&" -> asmgen.out(" and P8ZP_SCRATCH_W1 | tax | tya | and P8ZP_SCRATCH_W1+1 | tay | txa")
|
||||
"|" -> asmgen.out(" ora P8ZP_SCRATCH_W1 | tax | tya | ora P8ZP_SCRATCH_W1+1 | tay | txa")
|
||||
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_W1 | tax | tya | eor P8ZP_SCRATCH_W1+1 | tay | txa")
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
else -> throw AssemblyError("invalid bitwise operator")
|
||||
}
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun optimizedLogicalAndOrExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
||||
if (expr.right.isSimple()) {
|
||||
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
||||
assignLogicalAndOrWithSimpleRightOperandByte(target, expr.left, expr.operator, expr.right)
|
||||
return true
|
||||
}
|
||||
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
||||
assignLogicalAndOrWithSimpleRightOperandByte(target, expr.right, expr.operator, expr.left)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.saveRegisterStack(CpuRegister.A, false)
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
when (expr.operator) {
|
||||
"and" -> TODO("logical and (with optional shortcircuit) ${expr.position}")
|
||||
"or" -> TODO("logical or (with optional shortcircuit) ${expr.position}")
|
||||
else -> throw AssemblyError("invalid logical operator")
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||
return true
|
||||
}
|
||||
else if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||
if (expr.right.isSimple()) {
|
||||
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
||||
assignLogicalAndOrWithSimpleRightOperandWord(target, expr.left, expr.operator, expr.right)
|
||||
return true
|
||||
}
|
||||
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
||||
assignLogicalAndOrWithSimpleRightOperandWord(target, expr.right, expr.operator, expr.left)
|
||||
return true
|
||||
}
|
||||
}
|
||||
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
||||
when (expr.operator) {
|
||||
"and" -> TODO("logical and (with optional shortcircuit) ${expr.position}")
|
||||
"or" -> TODO("logical or (with optional shortcircuit) ${expr.position}")
|
||||
else -> throw AssemblyError("invalid logical operator")
|
||||
}
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
return true
|
||||
@ -1709,7 +1758,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
return true
|
||||
}
|
||||
|
||||
private fun assignLogicalWithSimpleRightOperandByte(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
private fun assignBitwiseWithSimpleRightOperandByte(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A, false)
|
||||
val operand = when(right) {
|
||||
is PtNumber -> "#${right.number.toHex()}"
|
||||
@ -1717,33 +1766,41 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
else -> throw AssemblyError("wrong right operand type")
|
||||
}
|
||||
when (operator) {
|
||||
"&", "and" -> asmgen.out(" and $operand")
|
||||
"|", "or" -> asmgen.out(" ora $operand")
|
||||
"&" -> asmgen.out(" and $operand")
|
||||
"|" -> asmgen.out(" ora $operand")
|
||||
"^", "xor" -> asmgen.out(" eor $operand")
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||
}
|
||||
|
||||
private fun assignLogicalWithSimpleRightOperandWord(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
private fun assignLogicalAndOrWithSimpleRightOperandByte(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
when (operator) {
|
||||
"and" -> TODO("logical and (with optional shortcircuit) ${left.position}")
|
||||
"or" -> TODO("logical or (with optional shortcircuit) ${left.position}")
|
||||
else -> throw AssemblyError("invalid logical operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignBitwiseWithSimpleRightOperandWord(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
assignExpressionToRegister(left, RegisterOrPair.AY, false)
|
||||
when(right) {
|
||||
is PtNumber -> {
|
||||
val number = right.number.toHex()
|
||||
when (operator) {
|
||||
"&", "and" -> asmgen.out(" and #<$number | tax | tya | and #>$number | tay | txa")
|
||||
"|", "or" -> asmgen.out(" ora #<$number | tax | tya | ora #>$number | tay | txa")
|
||||
"&" -> asmgen.out(" and #<$number | tax | tya | and #>$number | tay | txa")
|
||||
"|" -> asmgen.out(" ora #<$number | tax | tya | ora #>$number | tay | txa")
|
||||
"^", "xor" -> asmgen.out(" eor #<$number | tax | tya | eor #>$number | tay | txa")
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
else -> throw AssemblyError("invalid bitwise operator")
|
||||
}
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val name = asmgen.asmSymbolName(right)
|
||||
when (operator) {
|
||||
"&", "and" -> asmgen.out(" and $name | tax | tya | and $name+1 | tay | txa")
|
||||
"|", "or" -> asmgen.out(" ora $name | tax | tya | ora $name+1 | tay | txa")
|
||||
"&" -> asmgen.out(" and $name | tax | tya | and $name+1 | tay | txa")
|
||||
"|" -> asmgen.out(" ora $name | tax | tya | ora $name+1 | tay | txa")
|
||||
"^", "xor" -> asmgen.out(" eor $name | tax | tya | eor $name+1 | tay | txa")
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
else -> throw AssemblyError("invalid bitwise operator")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("wrong right operand type")
|
||||
@ -1751,6 +1808,26 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
}
|
||||
|
||||
private fun assignLogicalAndOrWithSimpleRightOperandWord(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
when(right) {
|
||||
is PtNumber -> {
|
||||
when (operator) {
|
||||
"and" -> TODO("logical and (with optional shortcircuit) ${left.position}")
|
||||
"or" -> TODO("logical or (with optional shortcircuit) ${left.position}")
|
||||
else -> throw AssemblyError("invalid logical operator")
|
||||
}
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
when (operator) {
|
||||
"and" -> TODO("logical and (with optional shortcircuit) ${left.position}")
|
||||
"or" -> TODO("logical or (with optional shortcircuit) ${left.position}")
|
||||
else -> throw AssemblyError("invalid logical operator")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("wrong right operand type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun attemptAssignToByteCompareZero(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
when (expr.operator) {
|
||||
"==" -> {
|
||||
|
@ -367,9 +367,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
"*" -> operatorMultiply(binExpr, vmDt)
|
||||
"/" -> operatorDivide(binExpr, vmDt, signed)
|
||||
"%" -> operatorModulo(binExpr, vmDt)
|
||||
"|" -> operatorOr(binExpr, vmDt)
|
||||
"&" -> operatorAnd(binExpr, vmDt)
|
||||
"^" -> operatorXor(binExpr, vmDt)
|
||||
"|" -> operatorOr(binExpr, vmDt, true)
|
||||
"&" -> operatorAnd(binExpr, vmDt, true)
|
||||
"^", "xor" -> operatorXor(binExpr, vmDt)
|
||||
"or" -> operatorOr(binExpr, vmDt, false)
|
||||
"and" -> operatorAnd(binExpr, vmDt, false)
|
||||
"<<" -> operatorShiftLeft(binExpr, vmDt)
|
||||
">>" -> operatorShiftRight(binExpr, vmDt, signed)
|
||||
"==" -> operatorEquals(binExpr, vmDt, false)
|
||||
@ -695,9 +697,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
|
||||
private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: IRDataType, bitwise: Boolean): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
if(codeGen.options.shortCircuit && (!binExpr.left.isSimple() && !binExpr.right.isSimple())) {
|
||||
if(!bitwise && codeGen.options.shortCircuit && (!binExpr.left.isSimple() && !binExpr.right.isSimple())) {
|
||||
// short-circuit LEFT and RIGHT --> if LEFT then RIGHT else LEFT (== if !LEFT then LEFT else RIGHT)
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
@ -724,9 +726,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun operatorOr(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
|
||||
private fun operatorOr(binExpr: PtBinaryExpression, vmDt: IRDataType, bitwise: Boolean): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
if(codeGen.options.shortCircuit && (!binExpr.left.isSimple() && !binExpr.right.isSimple())) {
|
||||
if(!bitwise && codeGen.options.shortCircuit && (!binExpr.left.isSimple() && !binExpr.right.isSimple())) {
|
||||
// short-circuit LEFT or RIGHT --> if LEFT then LEFT else RIGHT
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
|
@ -74,16 +74,8 @@ internal class BoolRemover(val program: Program) : AstWalker() {
|
||||
}
|
||||
|
||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
// convert boolean and/or/xor/not operators to bitwise equivalents.
|
||||
// so that codegen only has to work with bitwise boolean operations from now on.
|
||||
// note: this has to be done here and not in BeforeAsmTypecastCleaner! (code size will increase if done there...)
|
||||
if(expr.operator in setOf("and", "or", "xor")) {
|
||||
expr.operator = when(expr.operator) {
|
||||
"and" -> "&"
|
||||
"or" -> "|"
|
||||
"xor" -> "^"
|
||||
else -> "invalid"
|
||||
}
|
||||
// see if any of the arguments to a logical boolean expression need type casting to bool
|
||||
val mods = mutableListOf<IAstModification>()
|
||||
val newLeft = wrapWithBooleanCastIfNeeded(expr.left, program)
|
||||
val newRight = wrapWithBooleanCastIfNeeded(expr.right, program)
|
||||
|
@ -305,8 +305,8 @@ class TestOptimization: FunSpec({
|
||||
ubyte a1
|
||||
ubyte a2
|
||||
a1 = not not a1 ; a1 = a1==0
|
||||
a1 = not a1 or not a2 ; a1 = a1==0 | a2==0
|
||||
a1 = not a1 and not a2 ; a1 = a1==0 & a2==0
|
||||
a1 = not a1 or not a2 ; a1 = a1==0 or a2==0
|
||||
a1 = not a1 and not a2 ; a1 = a1==0 and a2==0
|
||||
}
|
||||
}
|
||||
"""
|
||||
@ -319,8 +319,8 @@ class TestOptimization: FunSpec({
|
||||
val value3 = (stmts[6] as Assignment).value as BinaryExpression
|
||||
value1.operator shouldBe "=="
|
||||
value1.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
value2.operator shouldBe "|"
|
||||
value3.operator shouldBe "&"
|
||||
value2.operator shouldBe "or"
|
||||
value3.operator shouldBe "and"
|
||||
}
|
||||
|
||||
test("asmgen correctly deals with float typecasting in augmented assignment") {
|
||||
|
@ -60,7 +60,7 @@ class TestTypecasts: FunSpec({
|
||||
val stmts2 = result2.compilerAst.entrypoint.statements
|
||||
stmts2.size shouldBe 5
|
||||
val expr2 = (stmts2[3] as Assignment).value as BinaryExpression
|
||||
expr2.operator shouldBe "&"
|
||||
expr2.operator shouldBe "and"
|
||||
expr2.right shouldBe NumericLiteral(DataType.UBYTE, 1.0, Position.DUMMY)
|
||||
}
|
||||
|
||||
@ -93,18 +93,18 @@ main {
|
||||
ubyte ub3
|
||||
ub3 = 1
|
||||
ubyte @shared bvalue
|
||||
bvalue = ub1 ^ ub2 ^ ub3 ^ true
|
||||
bvalue = (((ub1^ub2)^ub3)^(ftrue(99)!=0))
|
||||
bvalue = ((ub1&ub2)&(ftrue(99)!=0))
|
||||
bvalue = ub1 xor ub2 xor ub3 xor true
|
||||
bvalue = (((ub1 xor ub2)xor ub3) xor (ftrue(99)!=0))
|
||||
bvalue = ((ub1 and ub2) and (ftrue(99)!=0))
|
||||
return
|
||||
*/
|
||||
stmts.size shouldBe 11
|
||||
val assignValue1 = (stmts[7] as Assignment).value as BinaryExpression
|
||||
val assignValue2 = (stmts[8] as Assignment).value as BinaryExpression
|
||||
val assignValue3 = (stmts[9] as Assignment).value as BinaryExpression
|
||||
assignValue1.operator shouldBe "^"
|
||||
assignValue2.operator shouldBe "^"
|
||||
assignValue3.operator shouldBe "&"
|
||||
assignValue1.operator shouldBe "xor"
|
||||
assignValue2.operator shouldBe "xor"
|
||||
assignValue3.operator shouldBe "and"
|
||||
val right2 = assignValue2.right as BinaryExpression
|
||||
val right3 = assignValue3.right as BinaryExpression
|
||||
right2.operator shouldBe "!="
|
||||
@ -115,24 +115,6 @@ main {
|
||||
right3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
}
|
||||
|
||||
test("simple logical with bool no typecast") {
|
||||
val text="""
|
||||
main {
|
||||
bool bb
|
||||
|
||||
sub start() {
|
||||
bb = bb and 123
|
||||
}
|
||||
}"""
|
||||
val result = compileText(C64Target(), true, text, writeAssembly = true)!!
|
||||
val stmts = result.compilerAst.entrypoint.statements
|
||||
stmts.size shouldBe 2
|
||||
val assignValue = (stmts[0] as Assignment).value as BinaryExpression
|
||||
assignValue.left shouldBe instanceOf<IdentifierReference>()
|
||||
assignValue.operator shouldBe "&"
|
||||
(assignValue.right as NumericLiteral).number shouldBe 1.0
|
||||
}
|
||||
|
||||
test("simple logical with byte instead of bool ok with typecasting") {
|
||||
val text="""
|
||||
main {
|
||||
@ -147,7 +129,7 @@ main {
|
||||
stmts.size shouldBe 2
|
||||
val assignValue = (stmts[0] as Assignment).value as BinaryExpression
|
||||
assignValue.left shouldBe instanceOf<BinaryExpression>() // as a result of the cast to boolean
|
||||
assignValue.operator shouldBe "&"
|
||||
assignValue.operator shouldBe "and"
|
||||
(assignValue.right as NumericLiteral).number shouldBe 1.0
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,10 @@ TODO
|
||||
====
|
||||
|
||||
- [on branch: shortcircuit] complete McCarthy evaluation. This may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||
- vm ircodegen (DONE)
|
||||
- note: shortcircuit only on logical boolean expressions (and,or) not on bitwise (&,|)
|
||||
- vm ircodegen (DONE!)
|
||||
- in 6502 codegen (see vm's ExpressionGen operatorAnd / operatorOr)
|
||||
|
||||
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? Bitwise operations, etc), but only after setting the status bits is verified!
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
@ -47,6 +47,24 @@ main {
|
||||
txt.nl()
|
||||
@($4000) &= 22
|
||||
|
||||
txt.print("\n5a:\n")
|
||||
result = bool_true() or bool_false()
|
||||
txt.print("\n5b:\n")
|
||||
result = bool_true() and bool_false()
|
||||
txt.print("\n5c:\n")
|
||||
result = bool_false() and bool_true()
|
||||
txt.print("\n5d:\n")
|
||||
result = bool_false() xor bool_true()
|
||||
|
||||
|
||||
sub bool_true() -> bool {
|
||||
txt.print("bool_true\n")
|
||||
return true
|
||||
}
|
||||
sub bool_false() -> bool {
|
||||
txt.print("bool_false\n")
|
||||
return false
|
||||
}
|
||||
sub calc_a1() -> ubyte {
|
||||
txt.print("calc_a1\n")
|
||||
return a1+zero
|
||||
|
Loading…
Reference in New Issue
Block a user