mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
logical and/or/xor/not all replaced by bitwise &,|,^,~ (ast, codegens)
this also fixed some invalid outcomes of logical expressions!
This commit is contained in:
parent
8e36fe6bef
commit
965340ff90
@ -73,6 +73,7 @@ class PtBuiltinFunctionCall(val name: String,
|
||||
|
||||
|
||||
class PtBinaryExpression(val operator: String, type: DataType, position: Position): PtExpression(type, position) {
|
||||
// note: "and", "or", "xor" do not occur anymore as operators. They've been replaced int the ast by their bitwise versions &, |, ^.
|
||||
val left: PtExpression
|
||||
get() = children[0] as PtExpression
|
||||
val right: PtExpression
|
||||
|
@ -1,10 +1,9 @@
|
||||
package prog8.code.core
|
||||
|
||||
val AssociativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=")
|
||||
val AssociativeOperators = setOf("+", "*", "&", "|", "^", "==", "!=")
|
||||
val ComparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=")
|
||||
val AugmentAssignmentOperators = setOf("+", "-", "/", "*", "&", "|", "^", "<<", ">>", "%", "and", "or", "xor")
|
||||
val LogicalOperators = setOf("and", "or", "xor", "not")
|
||||
val BitwiseOperators = setOf("&", "|", "^")
|
||||
val AugmentAssignmentOperators = setOf("+", "-", "/", "*", "&", "|", "^", "<<", ">>", "%")
|
||||
val BitwiseOperators = setOf("&", "|", "^", "~")
|
||||
|
||||
fun invertedComparisonOperator(operator: String) =
|
||||
when (operator) {
|
||||
|
@ -768,9 +768,6 @@ internal class ExpressionsAsmGen(private val program: Program,
|
||||
"&" -> asmgen.out(" jsr prog8_lib.bitand_b")
|
||||
"^" -> asmgen.out(" jsr prog8_lib.bitxor_b")
|
||||
"|" -> asmgen.out(" jsr prog8_lib.bitor_b")
|
||||
"and" -> asmgen.out(" jsr prog8_lib.and_b")
|
||||
"or" -> asmgen.out(" jsr prog8_lib.or_b")
|
||||
"xor" -> asmgen.out(" jsr prog8_lib.xor_b")
|
||||
else -> throw AssemblyError("invalid operator $operator")
|
||||
}
|
||||
}
|
||||
@ -802,9 +799,6 @@ internal class ExpressionsAsmGen(private val program: Program,
|
||||
"&" -> asmgen.out(" jsr prog8_lib.bitand_w")
|
||||
"^" -> asmgen.out(" jsr prog8_lib.bitxor_w")
|
||||
"|" -> asmgen.out(" jsr prog8_lib.bitor_w")
|
||||
"and" -> asmgen.out(" jsr prog8_lib.and_w")
|
||||
"or" -> asmgen.out(" jsr prog8_lib.or_w")
|
||||
"xor" -> asmgen.out(" jsr prog8_lib.xor_w")
|
||||
else -> throw AssemblyError("invalid operator $operator")
|
||||
}
|
||||
}
|
||||
@ -821,7 +815,7 @@ internal class ExpressionsAsmGen(private val program: Program,
|
||||
">=" -> asmgen.out(" jsr floats.greatereq_f")
|
||||
"==" -> asmgen.out(" jsr floats.equal_f")
|
||||
"!=" -> asmgen.out(" jsr floats.notequal_f")
|
||||
"%", "<<", ">>", "&", "^", "|", "and", "or", "xor" -> throw AssemblyError("requires integer datatype")
|
||||
"%", "<<", ">>", "&", "^", "|" -> throw AssemblyError("requires integer datatype")
|
||||
else -> throw AssemblyError("invalid operator $operator")
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,10 @@ package prog8.codegen.cpu6502
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.expressions.AddressOf
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.assignment.AsmAssignSource
|
||||
|
@ -2,7 +2,6 @@ package prog8.codegen.cpu6502.assignment
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.getTempRegisterName
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.AsmGen
|
||||
@ -321,64 +320,6 @@ internal class AssignmentAsmGen(private val program: Program,
|
||||
if(!expr.inferType(program).isInteger)
|
||||
return false
|
||||
|
||||
// optimized code for logical expressions
|
||||
// note: due to boolean() wrapping of operands, we can use simple bitwise and/or/xor
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else during the use of this...
|
||||
if(expr.operator=="and") {
|
||||
val iDt = expr.left.inferType(program)
|
||||
val dt = iDt.getOrElse { throw AssemblyError("weird dt") }
|
||||
if (dt in ByteDatatypes) {
|
||||
val tmpReg = getTempRegisterName(iDt).joinToString(".")
|
||||
assignExpressionToVariable(expr.left, tmpReg, dt, expr.definingSubroutine)
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.A, dt==DataType.BYTE || dt==DataType.WORD)
|
||||
asmgen.out(" and $tmpReg")
|
||||
if(assign.target.datatype in ByteDatatypes)
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
else {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else throw AssemblyError("weird dt for and, expected byte $expr @${expr.position}")
|
||||
}
|
||||
else if(expr.operator=="or") {
|
||||
val iDt = expr.left.inferType(program)
|
||||
val dt = iDt.getOrElse { throw AssemblyError("weird dt") }
|
||||
if (dt in ByteDatatypes) {
|
||||
val tmpReg = getTempRegisterName(iDt).joinToString(".")
|
||||
assignExpressionToVariable(expr.left, tmpReg, dt, expr.definingSubroutine)
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.A, dt==DataType.BYTE || dt==DataType.WORD)
|
||||
asmgen.out(" ora $tmpReg")
|
||||
if(assign.target.datatype in ByteDatatypes)
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
else {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else throw AssemblyError("weird dt for or, expected byte $expr @${expr.position}")
|
||||
}
|
||||
else if(expr.operator=="xor") {
|
||||
val iDt = expr.left.inferType(program)
|
||||
val dt = iDt.getOrElse { throw AssemblyError("weird dt") }
|
||||
if (dt in ByteDatatypes) {
|
||||
val tmpReg = getTempRegisterName(iDt).joinToString(".")
|
||||
assignExpressionToVariable(expr.left, tmpReg, dt, expr.definingSubroutine)
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.A, dt==DataType.BYTE || dt==DataType.WORD)
|
||||
asmgen.out(" eor $tmpReg")
|
||||
if(assign.target.datatype in ByteDatatypes)
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
else {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else throw AssemblyError("weird dt for xor, expected byte $expr @${expr.position}")
|
||||
}
|
||||
|
||||
if(expr.operator!="+" && expr.operator!="-")
|
||||
return false
|
||||
|
||||
|
@ -390,9 +390,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
bne -
|
||||
+""")
|
||||
}
|
||||
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
|
||||
"&" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"|" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
"^" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
asmgen.storeAIntoZpPointerVar(sourceName)
|
||||
@ -427,9 +427,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
bne -
|
||||
+""")
|
||||
}
|
||||
"&", "and" -> asmgen.out(" and $otherName")
|
||||
"|", "or" -> asmgen.out(" ora $otherName")
|
||||
"^", "xor" -> asmgen.out(" eor $otherName")
|
||||
"&" -> asmgen.out(" and $otherName")
|
||||
"|" -> asmgen.out(" ora $otherName")
|
||||
"^" -> asmgen.out(" eor $otherName")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
asmgen.storeAIntoZpPointerVar(sourceName)
|
||||
@ -484,17 +484,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.storeAIntoZpPointerVar(sourceName)
|
||||
}
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
|
||||
asmgen.out(" and #$value")
|
||||
asmgen.storeAIntoZpPointerVar(sourceName)
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|"-> {
|
||||
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
|
||||
asmgen.out(" ora #$value")
|
||||
asmgen.storeAIntoZpPointerVar(sourceName)
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
|
||||
asmgen.out(" eor #$value")
|
||||
asmgen.storeAIntoZpPointerVar(sourceName)
|
||||
@ -562,15 +562,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
+""")
|
||||
}
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.out(" and $name | sta $name")
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.out(" ora $name | sta $name")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.out(" eor $name | sta $name")
|
||||
}
|
||||
@ -648,9 +648,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
+""")
|
||||
}
|
||||
}
|
||||
"&", "and" -> asmgen.out(" lda $name | and $otherName | sta $name")
|
||||
"|", "or" -> asmgen.out(" lda $name | ora $otherName | sta $name")
|
||||
"^", "xor" -> asmgen.out(" lda $name | eor $otherName | sta $name")
|
||||
"&" -> asmgen.out(" lda $name | and $otherName | sta $name")
|
||||
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name")
|
||||
"^" -> asmgen.out(" lda $name | eor $otherName | sta $name")
|
||||
"==" -> {
|
||||
asmgen.out("""
|
||||
lda $otherName
|
||||
@ -739,9 +739,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
"&", "and" -> asmgen.out(" lda $name | and #$value | sta $name")
|
||||
"|", "or" -> asmgen.out(" lda $name | ora #$value | sta $name")
|
||||
"^", "xor" -> asmgen.out(" lda $name | eor #$value | sta $name")
|
||||
"&" -> asmgen.out(" lda $name | and #$value | sta $name")
|
||||
"|" -> asmgen.out(" lda $name | ora #$value | sta $name")
|
||||
"^" -> asmgen.out(" lda $name | eor #$value | sta $name")
|
||||
"==" -> {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
@ -784,15 +784,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sbc P8ZP_SCRATCH_B1
|
||||
sta $name""")
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
|
||||
asmgen.out(" ora $name | sta $name")
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
|
||||
asmgen.out(" and $name | sta $name")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
|
||||
asmgen.out(" eor $name | sta $name")
|
||||
}
|
||||
@ -827,11 +827,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
dec $name+1
|
||||
+""")
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
|
||||
asmgen.out(" ora $name | sta $name")
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
|
||||
asmgen.out(" and $name | sta $name")
|
||||
if(dt in WordDatatypes) {
|
||||
@ -841,7 +841,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" lda #0 | sta $name+1")
|
||||
}
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
|
||||
asmgen.out(" eor $name | sta $name")
|
||||
}
|
||||
@ -1058,7 +1058,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
when {
|
||||
value == 0 -> {
|
||||
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||
@ -1095,7 +1095,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else -> asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1")
|
||||
}
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
when {
|
||||
value == 0 -> {}
|
||||
value and 255 == 0 -> asmgen.out(" lda $name+1 | ora #>$value | sta $name+1")
|
||||
@ -1103,7 +1103,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else -> asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1")
|
||||
}
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
when {
|
||||
value == 0 -> {}
|
||||
value and 255 == 0 -> asmgen.out(" lda $name+1 | eor #>$value | sta $name+1")
|
||||
@ -1267,7 +1267,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
+""")
|
||||
}
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
asmgen.out(" lda $otherName | and $name | sta $name")
|
||||
if(dt in WordDatatypes) {
|
||||
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||
@ -1276,8 +1276,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" lda #0 | sta $name+1")
|
||||
}
|
||||
}
|
||||
"|", "or" -> asmgen.out(" lda $otherName | ora $name | sta $name")
|
||||
"^", "xor" -> asmgen.out(" lda $otherName | eor $name | sta $name")
|
||||
"|" -> asmgen.out(" lda $otherName | ora $name | sta $name")
|
||||
"^" -> asmgen.out(" lda $otherName | eor $name | sta $name")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
}
|
||||
@ -1348,9 +1348,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
""")
|
||||
}
|
||||
"<<", ">>" -> throw AssemblyError("shift by a word value not supported, max is a byte")
|
||||
"&", "and" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1")
|
||||
"|", "or" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1")
|
||||
"^", "xor" -> asmgen.out(" lda $name | eor $otherName | sta $name | lda $name+1 | eor $otherName+1 | sta $name+1")
|
||||
"&" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1")
|
||||
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1")
|
||||
"^" -> asmgen.out(" lda $name | eor $otherName | sta $name | lda $name+1 | eor $otherName+1 | sta $name+1")
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
}
|
||||
}
|
||||
@ -1520,7 +1520,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
bne -
|
||||
+""")
|
||||
}
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.out(" and $name | sta $name")
|
||||
if(dt in WordDatatypes) {
|
||||
@ -1530,11 +1530,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" lda #0 | sta $name+1")
|
||||
}
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.out(" ora $name | sta $name")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
asmgen.out(" eor $name | sta $name")
|
||||
}
|
||||
@ -1566,15 +1566,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
remainderVarByWordInAY()
|
||||
}
|
||||
"<<", ">>" -> throw AssemblyError("shift by a word value not supported, max is a byte")
|
||||
"&", "and" -> {
|
||||
"&" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY)
|
||||
asmgen.out(" and $name | sta $name | tya | and $name+1 | sta $name+1")
|
||||
}
|
||||
"|", "or" -> {
|
||||
"|" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY)
|
||||
asmgen.out(" ora $name | sta $name | tya | ora $name+1 | sta $name+1")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
"^" -> {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY)
|
||||
asmgen.out(" eor $name | sta $name | tya | eor $name+1 | sta $name+1")
|
||||
}
|
||||
|
@ -251,9 +251,9 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
"*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister)
|
||||
"/" -> operatorDivide(binExpr, vmDt, resultRegister, resultFpRegister, signed)
|
||||
"%" -> operatorModulo(binExpr, vmDt, resultRegister)
|
||||
"|", "or" -> operatorOr(binExpr, vmDt, resultRegister)
|
||||
"&", "and" -> operatorAnd(binExpr, vmDt, resultRegister)
|
||||
"^", "xor" -> operatorXor(binExpr, vmDt, resultRegister)
|
||||
"|" -> operatorOr(binExpr, vmDt, resultRegister)
|
||||
"&" -> operatorAnd(binExpr, vmDt, resultRegister)
|
||||
"^" -> operatorXor(binExpr, vmDt, resultRegister)
|
||||
"<<" -> operatorShiftLeft(binExpr, vmDt, resultRegister)
|
||||
">>" -> operatorShiftRight(binExpr, vmDt, resultRegister, signed)
|
||||
"==" -> operatorEquals(binExpr, vmDt, resultRegister, false)
|
||||
|
@ -22,9 +22,6 @@ class ConstExprEvaluator {
|
||||
"&" -> bitwiseand(left, right)
|
||||
"|" -> bitwiseor(left, right)
|
||||
"^" -> bitwisexor(left, right)
|
||||
"and" -> logicaland(left, right) // TODO bitwise and?
|
||||
"or" -> logicalor(left, right) // TODO bitwise or?
|
||||
"xor" -> logicalxor(left, right) // TODO bitwise xor?
|
||||
"<" -> NumericLiteral.fromBoolean(left < right, left.position)
|
||||
">" -> NumericLiteral.fromBoolean(left > right, left.position)
|
||||
"<=" -> NumericLiteral.fromBoolean(left <= right, left.position)
|
||||
@ -58,57 +55,6 @@ class ConstExprEvaluator {
|
||||
return NumericLiteral(left.type, result.toDouble(), left.position)
|
||||
}
|
||||
|
||||
private fun logicalxor(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
val error = "cannot compute $left logical-xor $right"
|
||||
return when (left.type) {
|
||||
in IntegerDatatypes -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteral.fromBoolean((left.number.toInt() != 0) xor (right.number.toInt() != 0), left.position)
|
||||
DataType.FLOAT -> NumericLiteral.fromBoolean((left.number.toInt() != 0) xor (right.number != 0.0), left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
DataType.FLOAT -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteral.fromBoolean((left.number != 0.0) xor (right.number.toInt() != 0), left.position)
|
||||
DataType.FLOAT -> NumericLiteral.fromBoolean((left.number != 0.0) xor (right.number != 0.0), left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun logicalor(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
val error = "cannot compute $left logical-or $right"
|
||||
return when (left.type) {
|
||||
in IntegerDatatypes -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteral.fromBoolean(left.number.toInt() != 0 || right.number.toInt() != 0, left.position)
|
||||
DataType.FLOAT -> NumericLiteral.fromBoolean(left.number.toInt() != 0 || right.number != 0.0, left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
DataType.FLOAT -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteral.fromBoolean(left.number != 0.0 || right.number.toInt() != 0, left.position)
|
||||
DataType.FLOAT -> NumericLiteral.fromBoolean(left.number != 0.0 || right.number != 0.0, left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun logicaland(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
val error = "cannot compute $left logical-and $right"
|
||||
return when (left.type) {
|
||||
in IntegerDatatypes -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteral.fromBoolean(left.number.toInt() != 0 && right.number.toInt() != 0, left.position)
|
||||
DataType.FLOAT -> NumericLiteral.fromBoolean(left.number.toInt() != 0 && right.number != 0.0, left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
DataType.FLOAT -> when (right.type) {
|
||||
in IntegerDatatypes -> NumericLiteral.fromBoolean(left.number != 0.0 && right.number.toInt() != 0, left.position)
|
||||
DataType.FLOAT -> NumericLiteral.fromBoolean(left.number != 0.0 && right.number != 0.0, left.position)
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
else -> throw ExpressionError(error, left.position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bitwisexor(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
if(left.type== DataType.UBYTE) {
|
||||
if(right.type in IntegerDatatypes) {
|
||||
|
@ -12,7 +12,10 @@ import prog8.ast.statements.IfElse
|
||||
import prog8.ast.statements.Jump
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.core.AssociativeOperators
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IntegerDatatypes
|
||||
import prog8.code.core.NumericDatatypes
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.log2
|
||||
import kotlin.math.pow
|
||||
@ -194,34 +197,8 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
|
||||
}
|
||||
|
||||
// simplify when a term is constant and directly determines the outcome
|
||||
val constTrue = NumericLiteral.fromBoolean(true, expr.position)
|
||||
val constFalse = NumericLiteral.fromBoolean(false, expr.position)
|
||||
val newExpr: Expression? = when (expr.operator) {
|
||||
"or" -> {
|
||||
when {
|
||||
leftVal != null && leftVal.asBooleanValue || rightVal != null && rightVal.asBooleanValue -> constTrue
|
||||
leftVal != null && !leftVal.asBooleanValue -> expr.right
|
||||
rightVal != null && !rightVal.asBooleanValue -> expr.left
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
"and" -> {
|
||||
when {
|
||||
leftVal != null && !leftVal.asBooleanValue || rightVal != null && !rightVal.asBooleanValue -> constFalse
|
||||
leftVal != null && leftVal.asBooleanValue -> expr.right
|
||||
rightVal != null && rightVal.asBooleanValue -> expr.left
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
"xor" -> {
|
||||
when {
|
||||
leftVal != null && !leftVal.asBooleanValue -> expr.right
|
||||
rightVal != null && !rightVal.asBooleanValue -> expr.left
|
||||
leftVal != null && leftVal.asBooleanValue -> BinaryExpression(expr.right, "==", NumericLiteral.optimalInteger(0, Position.DUMMY), expr.right.position)
|
||||
rightVal != null && rightVal.asBooleanValue -> BinaryExpression(expr.left, "==", NumericLiteral.optimalInteger(0, Position.DUMMY), expr.left.position)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
"|" -> {
|
||||
when {
|
||||
leftVal?.number==0.0 -> expr.right
|
||||
@ -318,25 +295,6 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(containment: ContainmentCheck, parent: Node): Iterable<IAstModification> {
|
||||
val range = containment.iterable as? RangeExpression
|
||||
if(range!=null && range.step.constValue(program)?.number==1.0) {
|
||||
val from = range.from.constValue(program)
|
||||
val to = range.to.constValue(program)
|
||||
val value = containment.element
|
||||
if(from!=null && to!=null && value.isSimple) {
|
||||
if(to.number-from.number>6.0) {
|
||||
// replace containment test with X>=from and X<=to
|
||||
val left = BinaryExpression(value, ">=", from, containment.position)
|
||||
val right = BinaryExpression(value.copy(), "<=", to, containment.position)
|
||||
val comparison = BinaryExpression(left, "and", right, containment.position)
|
||||
return listOf(IAstModification.ReplaceNode(containment, comparison, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
private fun determineY(x: Expression, subBinExpr: BinaryExpression): Expression? {
|
||||
return when {
|
||||
subBinExpr.left isSameAs x -> subBinExpr.right
|
||||
|
@ -121,98 +121,6 @@ bitxor_w .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
and_b .proc
|
||||
; -- logical and (of 2 bytes)
|
||||
lda P8ESTACK_LO+2,x
|
||||
beq +
|
||||
lda #1
|
||||
+ sta P8ZP_SCRATCH_B1
|
||||
lda P8ESTACK_LO+1,x
|
||||
beq +
|
||||
lda #1
|
||||
+ and P8ZP_SCRATCH_B1
|
||||
inx
|
||||
sta P8ESTACK_LO+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
or_b .proc
|
||||
; -- logical or (of 2 bytes)
|
||||
lda P8ESTACK_LO+2,x
|
||||
ora P8ESTACK_LO+1,x
|
||||
beq +
|
||||
lda #1
|
||||
+ inx
|
||||
sta P8ESTACK_LO+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
xor_b .proc
|
||||
; -- logical xor (of 2 bytes)
|
||||
lda P8ESTACK_LO+2,x
|
||||
beq +
|
||||
lda #1
|
||||
+ sta P8ZP_SCRATCH_B1
|
||||
lda P8ESTACK_LO+1,x
|
||||
beq +
|
||||
lda #1
|
||||
+ eor P8ZP_SCRATCH_B1
|
||||
inx
|
||||
sta P8ESTACK_LO+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
and_w .proc
|
||||
; -- logical and (word and word -> byte)
|
||||
lda P8ESTACK_LO+2,x
|
||||
ora P8ESTACK_HI+2,x
|
||||
beq +
|
||||
lda #1
|
||||
+ sta P8ZP_SCRATCH_B1
|
||||
lda P8ESTACK_LO+1,x
|
||||
ora P8ESTACK_HI+1,x
|
||||
beq +
|
||||
lda #1
|
||||
+ and P8ZP_SCRATCH_B1
|
||||
inx
|
||||
sta P8ESTACK_LO+1,x
|
||||
sta P8ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
or_w .proc
|
||||
; -- logical or (word or word -> byte)
|
||||
lda P8ESTACK_LO+2,x
|
||||
ora P8ESTACK_LO+1,x
|
||||
ora P8ESTACK_HI+2,x
|
||||
ora P8ESTACK_HI+1,x
|
||||
beq +
|
||||
lda #1
|
||||
+ inx
|
||||
sta P8ESTACK_LO+1,x
|
||||
sta P8ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
xor_w .proc
|
||||
; -- logical xor (word xor word -> byte)
|
||||
lda P8ESTACK_LO+2,x
|
||||
ora P8ESTACK_HI+2,x
|
||||
beq +
|
||||
lda #1
|
||||
+ sta P8ZP_SCRATCH_B1
|
||||
lda P8ESTACK_LO+1,x
|
||||
ora P8ESTACK_HI+1,x
|
||||
beq +
|
||||
lda #1
|
||||
+ eor P8ZP_SCRATCH_B1
|
||||
inx
|
||||
sta P8ESTACK_LO+1,x
|
||||
sta P8ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
|
||||
add_w .proc
|
||||
; -- push word+word / uword+uword
|
||||
|
@ -859,11 +859,6 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("remainder can only be used on unsigned integer operands", expr.right.position)
|
||||
}
|
||||
}
|
||||
"and", "or", "xor" -> {
|
||||
// only integer numeric operands accepted
|
||||
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
|
||||
errors.err("logical operator can only be used on boolean operands", expr.right.position)
|
||||
}
|
||||
"&", "|", "^" -> {
|
||||
// only integer numeric operands accepted
|
||||
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
|
||||
|
@ -97,22 +97,35 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter, val comp
|
||||
return listOf(IAstModification.ReplaceNode(expr, containment, parent))
|
||||
}
|
||||
|
||||
// To enable simple bitwise and/or/xor/not instructions in the codegen for the logical and/or/xor/not,
|
||||
// we wrap the operands in a call to boolean() if required so that they are 0 or 1 as needed.
|
||||
// Making the codegen more generic to do this by itself all the time will generate much larger
|
||||
// code because it is hard to decide there if the value conversion to 0 or 1 is needed or not,
|
||||
// so a lot of useless checks and conversions are added. Here we can be smarter so the codegen
|
||||
// can just rely on the correct value of the operands (0 or 1) if they're boolean, and just use bitwise instructions.
|
||||
if(expr.operator in LogicalOperators) {
|
||||
// convert boolean and/or/xor/not operators to bitwise equivalents.
|
||||
// the rest of the ast and codegen only has to work with bitwise boolean operations from now on.
|
||||
if(expr.operator in setOf("and", "or", "xor")) {
|
||||
expr.operator = when(expr.operator) {
|
||||
"and" -> "&"
|
||||
"or" -> "|"
|
||||
"xor" -> "^"
|
||||
else -> "invalid"
|
||||
}
|
||||
return listOf(
|
||||
IAstModification.ReplaceNodeSafe(expr.left, wrapWithBooleanConversion(expr.left), expr),
|
||||
IAstModification.ReplaceNodeSafe(expr.right, wrapWithBooleanConversion(expr.right), expr)
|
||||
IAstModification.ReplaceNodeSafe(expr.right, wrapWithBooleanConversion(expr.right), expr),
|
||||
)
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(expr.operator == "not") {
|
||||
// not(x) --> x==0
|
||||
// this means that "not" will never occur anywhere again in the ast after this
|
||||
val dt = expr.expression.inferType(program).getOr(DataType.UBYTE)
|
||||
val replacement = BinaryExpression(expr.expression, "==", NumericLiteral(dt,0.0, expr.position), expr.position)
|
||||
return listOf(IAstModification.ReplaceNodeSafe(expr, replacement, parent))
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||
val nextAssignment = decl.nextSibling() as? Assignment
|
||||
if(nextAssignment!=null && nextAssignment.origin!=AssignmentOrigin.VARINIT) {
|
||||
@ -148,13 +161,25 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter, val comp
|
||||
}
|
||||
|
||||
private fun wrapWithBooleanConversion(expr: Expression): Expression {
|
||||
return if(expr is IFunctionCall && expr.target.nameInSource==listOf("boolean"))
|
||||
fun isBoolean(expr: Expression): Boolean {
|
||||
return if(expr is IFunctionCall && expr.target.nameInSource==listOf("boolean"))
|
||||
true
|
||||
else if(expr is BinaryExpression && expr.operator in ComparisonOperators+listOf("and", "or", "xor"))
|
||||
true
|
||||
else if(expr is PrefixExpression && expr.operator == "not")
|
||||
true
|
||||
else if(expr is BinaryExpression && expr.operator in BitwiseOperators) {
|
||||
if(isBoolean(expr.left) && isBoolean(expr.right))
|
||||
true
|
||||
else expr.operator=="&" && expr.right.constValue(program)?.number==1.0 // x & 1 is also a boolean result
|
||||
}
|
||||
else
|
||||
false
|
||||
}
|
||||
|
||||
return if(isBoolean(expr))
|
||||
expr
|
||||
else if(expr is BinaryExpression && expr.operator in LogicalOperators+ComparisonOperators)
|
||||
expr
|
||||
// else if(expr is PrefixExpression && expr.operator == "not") // TODO should work for 'not' too but now causes assembler to generate wrong code (even without optimizations)
|
||||
// expr
|
||||
else
|
||||
FunctionCallExpression(IdentifierReference(listOf("boolean"), expr.position), mutableListOf(expr), expr.position)
|
||||
BuiltinFunctionCall(IdentifierReference(listOf("boolean"), expr.position), mutableListOf(expr), expr.position)
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,10 @@ 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.Expression
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.IErrorReporter
|
||||
@ -88,17 +87,6 @@ internal class NotExpressionChanger(val program: Program, val errors: IErrorRepo
|
||||
}
|
||||
}
|
||||
|
||||
if(expr.operator=="==") {
|
||||
val rightValue = expr.right.constValue(program)
|
||||
if(rightValue?.number==0.0 && rightValue.type in IntegerDatatypes) {
|
||||
// x==0 -> not x (only if occurs as a subexpression)
|
||||
if(expr.parent is Expression || expr.parent is Assignment) {
|
||||
val notExpr = PrefixExpression("not", expr.left.copy(), expr.position)
|
||||
return listOf(IAstModification.ReplaceNodeSafe(expr, notExpr, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
@ -107,6 +95,27 @@ internal class NotExpressionChanger(val program: Program, val errors: IErrorRepo
|
||||
// not(not(x)) -> x
|
||||
if((expr.expression as? PrefixExpression)?.operator=="not")
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.expression, parent))
|
||||
// not(~x) -> x!=0
|
||||
if((expr.expression as? PrefixExpression)?.operator=="~") {
|
||||
val x = (expr.expression as PrefixExpression).expression
|
||||
val dt = x.inferType(program).getOrElse { throw FatalAstException("invalid dt") }
|
||||
val notZero = BinaryExpression(x, "!=", NumericLiteral(dt, 0.0, expr.position), expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, notZero, parent))
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
@ -71,22 +71,15 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
// +X --> X
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.expression, parent))
|
||||
}
|
||||
else if(expr.operator == "not") {
|
||||
// not(x) --> x==0
|
||||
// this means that "not" will never occur anywhere again in the ast after this
|
||||
val dt = expr.expression.inferType(program).getOr(DataType.UBYTE)
|
||||
val replacement = BinaryExpression(expr.expression, "==", NumericLiteral(dt,0.0, expr.position), expr.position)
|
||||
return listOf(IAstModification.ReplaceNodeSafe(expr, replacement, parent))
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
// try to replace a multi-comparison expression (if x==1 or x==2 or x==3 ... ) by a simple containment check.
|
||||
// try to replace a multi-comparison expression (if x==1 | x==2 | x==3 ... ) by a simple containment check.
|
||||
// but only if the containment check is the top-level expression.
|
||||
if(parent is BinaryExpression)
|
||||
return noModifications
|
||||
if(expr.operator == "or") {
|
||||
if(expr.operator == "|") {
|
||||
val leftBinExpr1 = expr.left as? BinaryExpression
|
||||
val rightBinExpr1 = expr.right as? BinaryExpression
|
||||
|
||||
@ -102,7 +95,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
}
|
||||
return false
|
||||
}
|
||||
if(expr.operator!="or")
|
||||
if(expr.operator!="|")
|
||||
return false
|
||||
val leftBinExpr = expr.left as? BinaryExpression
|
||||
val rightBinExpr = expr.right as? BinaryExpression
|
||||
@ -227,15 +220,11 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
|
||||
override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(functionCallExpr.target.nameInSource==listOf("boolean")) {
|
||||
// boolean(expr) can be removed if expr is a logical expression or comparison expression itself, or boolean()
|
||||
// boolean(expr) can be removed if expr is a comparison expression, or nested boolean()
|
||||
val binexpr = functionCallExpr.args.single() as? BinaryExpression
|
||||
if(binexpr!=null && binexpr.operator in LogicalOperators + ComparisonOperators) {
|
||||
if(binexpr!=null && binexpr.operator in ComparisonOperators) {
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr, binexpr, parent))
|
||||
}
|
||||
val prefixExpression = functionCallExpr.args.single() as? PrefixExpression
|
||||
if(prefixExpression!=null && prefixExpression.operator in LogicalOperators) {
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr, prefixExpression, parent))
|
||||
}
|
||||
val fcall = functionCallExpr.args.single() as? IFunctionCall
|
||||
if(fcall!=null && fcall.target.nameInSource==listOf("boolean")) {
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr, fcall as Node, parent))
|
||||
|
@ -11,7 +11,6 @@ import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.ast.statements.Label
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.compileFile
|
||||
import kotlin.io.path.name
|
||||
|
||||
|
||||
|
@ -18,8 +18,8 @@ import prog8.code.core.Position
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
import prog8tests.helpers.cartesianProduct
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
|
||||
/**
|
||||
|
@ -649,6 +649,7 @@ class TestOptimization: FunSpec({
|
||||
}
|
||||
}"""
|
||||
val result = compileText(C64Target(), optimize=true, src, writeAssembly=false)!!
|
||||
printProgram(result.program)
|
||||
/*
|
||||
expected result:
|
||||
ubyte[] auto_heap_var = [1,4,99,3]
|
||||
|
@ -23,8 +23,6 @@ import prog8.code.target.cbm.PetsciiEncoding
|
||||
import prog8.parser.ParseError
|
||||
import prog8.parser.Prog8Parser.parseModule
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.name
|
||||
|
@ -15,11 +15,6 @@ import prog8.code.target.c64.C64Zeropage
|
||||
import prog8.codegen.cpu6502.AsmGen
|
||||
import prog8.compiler.astprocessing.SymbolTableMaker
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
class TestAsmGenSymbols: StringSpec({
|
||||
fun createTestProgram(): Program {
|
||||
|
@ -325,7 +325,6 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
||||
override fun visit(assignment: Assignment) {
|
||||
val binExpr = assignment.value as? BinaryExpression
|
||||
if(binExpr!=null && binExpr.left isSameAs assignment.target
|
||||
&& binExpr.operator !in arrayOf("and", "or", "xor")
|
||||
&& binExpr.operator !in ComparisonOperators) {
|
||||
// we only support the inplace assignments of the form A = A <operator> <value>
|
||||
assignment.target.accept(this)
|
||||
|
@ -1,7 +1,10 @@
|
||||
package prog8.ast
|
||||
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.InferredTypes
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.Position
|
||||
|
@ -3,6 +3,8 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- re-enable unittest "various 'not' operator rewrites even without optimizations on" when not-problem is fixed
|
||||
|
||||
- petaxian roller.p8 line 49 (also see test.p8) generates large code compared to 8.2
|
||||
|
||||
- code gen for if statements has become inefficient? vm/6502?
|
||||
@ -17,15 +19,6 @@ For next release
|
||||
|
||||
- petaxian.prg became quite a bit (200 bytes) larger, why!? because of the above?
|
||||
|
||||
- get rid of logical and/or/xor in the codegen (6502+vm)
|
||||
because bitwise versions + correct use of boolean() operand wrapping are equivalent?
|
||||
can do this for instance by replacing and/or/xor with their bitwise versions &, |, ^
|
||||
- ...or: 6502: fix logical and/or/xor routines to just be bitwise routines.
|
||||
|
||||
- not-problem: assembler generates faulty code when in wrapWithBooleanConversion() the "not" rule is enabled
|
||||
so that these are not wrapped (even without optimizations)
|
||||
- re-enable unittest "various 'not' operator rewrites even without optimizations on" when not-problem is fixed
|
||||
|
||||
- compiling logical.p8 to virtual with optimization generates a lot larger code as without optimizations.
|
||||
this is not the case for the 6502 codegen.
|
||||
|
||||
|
@ -9,6 +9,39 @@ main {
|
||||
|
||||
ubyte a1 = 0
|
||||
ubyte a2 = 128
|
||||
uword w1 = 0
|
||||
|
||||
; if not a1 and not w1
|
||||
; txt.print("1")
|
||||
; if (0==a1) and (0==w1)
|
||||
; txt.print("a")
|
||||
; txt.nl()
|
||||
a1 = 0
|
||||
w1 = 4096
|
||||
if not a1 and not w1
|
||||
txt.print("fail ")
|
||||
else
|
||||
txt.print("ok ")
|
||||
if (0==a1) and (0==w1)
|
||||
txt.print("fail ")
|
||||
else
|
||||
txt.print("ok ")
|
||||
txt.nl()
|
||||
|
||||
a1=128
|
||||
w1=2
|
||||
if not a1 and not w1
|
||||
txt.print("fail")
|
||||
if (0==a1) and (0==w1)
|
||||
txt.print("fail")
|
||||
txt.nl()
|
||||
w1=2
|
||||
if not a1 and not w1
|
||||
txt.print("fail")
|
||||
if (0==a1) and (0==w1)
|
||||
txt.print("fail")
|
||||
txt.nl()
|
||||
|
||||
|
||||
|
||||
|
||||
@ -17,17 +50,17 @@ main {
|
||||
; TODO cx16.r0 = a2 + 25 + (a1/40)
|
||||
; txt.setcc( a1, a2 + 25 + (a1/40), 11,22)
|
||||
|
||||
if a1 and a2 {
|
||||
a1++
|
||||
}
|
||||
|
||||
if not a1 or not a2 {
|
||||
a1++
|
||||
}
|
||||
|
||||
if a1!=99 and not a2 {
|
||||
a1++
|
||||
}
|
||||
; if a1 and a2 {
|
||||
; a1++
|
||||
; }
|
||||
;
|
||||
; if not a1 or not a2 {
|
||||
; a1++
|
||||
; }
|
||||
;
|
||||
; if a1!=99 and not a2 {
|
||||
; a1++
|
||||
; }
|
||||
|
||||
; while a1 != a2 {
|
||||
; a1++
|
||||
|
Loading…
x
Reference in New Issue
Block a user