diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index ac33f3879..5e3dd0031 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -142,11 +142,12 @@ private fun PtVariable.prefix(st: SymbolTable): PtVariable { return this val arrayValue = value as? PtArray - return if(arrayValue!=null && arrayValue.children.any { it !is PtNumber} ) { + return if(arrayValue!=null && arrayValue.children.any { it !is PtNumber && it !is PtBool } ) { val newValue = PtArray(arrayValue.type, arrayValue.position) arrayValue.children.forEach { elt -> when(elt) { is PtIdentifier -> newValue.add(elt.prefix(arrayValue, st)) + is PtBool -> newValue.add(elt) is PtNumber -> newValue.add(elt) is PtAddressOf -> { if(elt.definingBlock()?.options?.noSymbolPrefixing==true) @@ -624,7 +625,7 @@ class AsmGen6502Internal ( } when (expr.type) { - in ByteDatatypes -> { + in ByteDatatypesWithBoolean -> { assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register), false) } in WordDatatypes -> { @@ -691,7 +692,7 @@ class AsmGen6502Internal ( internal fun assignExpressionTo(value: PtExpression, target: AsmAssignTarget) { when (target.datatype) { - in ByteDatatypes -> { + in ByteDatatypesWithBoolean -> { if (value.asConstInteger()==0) { when(target.kind) { TargetStorageKind.VARIABLE -> { @@ -805,7 +806,7 @@ class AsmGen6502Internal ( } when(stmt.condition.type) { in WordDatatypes -> translateWordEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label) - in ByteDatatypes -> translateByteEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label) + in ByteDatatypesWithBoolean -> translateByteEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label) else -> throw AssemblyError("weird condition dt") } } else { @@ -813,7 +814,7 @@ class AsmGen6502Internal ( val endLabel = makeLabel("if_end") when(stmt.condition.type) { in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel) - in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel) + in ByteDatatypesWithBoolean -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel) else -> throw AssemblyError("weird condition dt") } translate(stmt.ifScope) @@ -825,7 +826,7 @@ class AsmGen6502Internal ( val endLabel = makeLabel("if_end") when(stmt.condition.type) { in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel) - in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel) + in ByteDatatypesWithBoolean -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel) else -> throw AssemblyError("weird condition dt") } translate(stmt.ifScope) @@ -839,7 +840,7 @@ class AsmGen6502Internal ( private fun requireComparisonExpression(condition: PtExpression) { if (!(condition is PtBinaryExpression && condition.operator in ComparisonOperators)) - throw AssemblyError("expected boolean comparison expression $condition") + throw AssemblyError("expected boolean comparison expression") } private fun translate(stmt: PtRepeatLoop) { @@ -1118,7 +1119,7 @@ $repeatLabel""") val sub = ret.definingSub()!! val returnReg = sub.returnRegister()!! when (sub.returntype) { - in NumericDatatypes -> { + in NumericDatatypes, DataType.BOOL -> { assignExpressionToRegister(returnvalue, returnReg.registerOrPair!!) } else -> { @@ -1256,6 +1257,7 @@ $repeatLabel""") return when(expr) { is PtIdentifier -> false is PtNumber -> false + is PtBool -> false is PtMemoryByte -> expr.address !is PtIdentifier && expr.address !is PtNumber is PtTypeCast -> evalBytevalueWillClobberA(expr.value) else -> true @@ -1344,7 +1346,7 @@ $repeatLabel""") // invert the comparison, so we can reuse the JumpIfFalse code generation routines val invertedComparisonOperator = invertedComparisonOperator(expr.operator) - ?: throw AssemblyError("can't invert comparison $expr") + ?: throw AssemblyError("can't invert comparison ${expr.operator} $expr") val left = expr.left val right = expr.right @@ -1383,7 +1385,7 @@ $repeatLabel""") jumpIfFalseLabel: String ) { val dt = left.type - if(dt in IntegerDatatypes && left is PtIdentifier) + if(dt in IntegerDatatypesWithBoolean && left is PtIdentifier) return testVariableZeroOrJumpElsewhere(left, dt, operator, jumpIfFalseLabel) when(dt) { @@ -1543,7 +1545,7 @@ $repeatLabel""") when (operator) { "==" -> { when (dt) { - in ByteDatatypes -> translateByteEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + in ByteDatatypesWithBoolean -> translateByteEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) in WordDatatypes -> translateWordEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) DataType.FLOAT -> translateFloatEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) DataType.STR -> translateStringEqualsOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) @@ -1552,7 +1554,7 @@ $repeatLabel""") } "!=" -> { when (dt) { - in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + in ByteDatatypesWithBoolean -> translateByteNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) DataType.FLOAT -> translateFloatNotEqualsOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) DataType.STR -> translateStringNotEqualsOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) @@ -2547,6 +2549,7 @@ $repeatLabel""") } when (right) { + is PtBool -> TODO("word equals for bool operand") is PtNumber -> { assignExpressionToRegister(left, RegisterOrPair.AY) val number = right.number.toHex() @@ -2635,6 +2638,7 @@ $repeatLabel""") } when (right) { + is PtBool -> TODO("word not equals for bool operand") is PtNumber -> { assignExpressionToRegister(left, RegisterOrPair.AY) val number = right.number.toHex() @@ -2669,6 +2673,7 @@ $repeatLabel""") } } else -> { + TODO("word not equals boolean in special case?") if(left.isSimple()) { assignExpressionToVariable(right, "P8ZP_SCRATCH_W2", DataType.UWORD) assignExpressionToRegister(left, RegisterOrPair.AY) @@ -2983,6 +2988,7 @@ $repeatLabel""") private fun wordJumpForSimpleLeftOperand(left: PtExpression, right: PtExpression, code: (String, String)->Unit): Boolean { when (left) { + is PtBool -> TODO("word jump for bool operand") is PtNumber -> { assignExpressionToRegister(right, RegisterOrPair.AY) val number = left.number.toHex() @@ -3010,32 +3016,44 @@ $repeatLabel""") } private fun byteJumpForSimpleRightOperand(left: PtExpression, right: PtExpression, code: (String)->Unit): Boolean { - if(right is PtNumber) { - assignExpressionToRegister(left, RegisterOrPair.A) - code("#${right.number.toHex()}") - return true - } - if(right is PtIdentifier) { - assignExpressionToRegister(left, RegisterOrPair.A) - code(asmVariableName(right)) - return true - } - var memread = right as? PtMemoryByte - if(memread==null && right is PtTypeCast) - memread = right.value as? PtMemoryByte - if(memread!=null) { - val address = memread.address as? PtNumber - if(address!=null) { + when (right) { + is PtBool -> { assignExpressionToRegister(left, RegisterOrPair.A) - code(address.number.toHex()) + code("#${right.asInt()} ; TODO can we get rid of this cmp when dealing with booleans?") // TODO can we get rid of the cmp when dealing with booleans? return true } + is PtNumber -> { + assignExpressionToRegister(left, RegisterOrPair.A) + code("#${right.number.toHex()}") + return true + } + + is PtIdentifier -> { + assignExpressionToRegister(left, RegisterOrPair.A) + code(asmVariableName(right)) + return true + } + + else -> { + var memread = right as? PtMemoryByte + if (memread == null && right is PtTypeCast) + memread = right.value as? PtMemoryByte + if (memread != null) { + val address = memread.address as? PtNumber + if (address != null) { + assignExpressionToRegister(left, RegisterOrPair.A) + code(address.number.toHex()) + return true + } + } + return false + } } - return false } private fun wordJumpForSimpleRightOperands(left: PtExpression, right: PtExpression, code: (String, String)->Unit): Boolean { when (right) { + is PtBool -> TODO("word jump for bool operand") is PtNumber -> { assignExpressionToRegister(left, RegisterOrPair.AY) val number = right.number.toHex() @@ -3077,7 +3095,7 @@ $repeatLabel""") out(" lda P8ZP_SCRATCH_REG") } else { - if (parameter.type in ByteDatatypes) { + if (parameter.type in ByteDatatypesWithBoolean) { if (isTargetCpu(CpuType.CPU65c02)) { when (reg.registerOrPair) { RegisterOrPair.A -> out(" pla") @@ -3135,7 +3153,7 @@ $repeatLabel""") } internal fun popCpuStack(dt: DataType) { - if (dt in ByteDatatypes) { + if (dt in ByteDatatypesWithBoolean) { out(" pla") } else if (dt in WordDatatypes) { if (isTargetCpu(CpuType.CPU65c02)) @@ -3149,7 +3167,7 @@ $repeatLabel""") internal fun pushCpuStack(dt: DataType, value: PtExpression) { val signed = value.type.oneOf(DataType.BYTE, DataType.WORD) - if(dt in ByteDatatypes) { + if(dt in ByteDatatypesWithBoolean) { assignExpressionToRegister(value, RegisterOrPair.A, signed) out(" pha") } else if(dt in WordDatatypes) { @@ -3176,7 +3194,7 @@ $repeatLabel""") } internal fun needAsaveForExpr(arg: PtExpression): Boolean = - arg !is PtNumber && arg !is PtIdentifier && (arg !is PtMemoryByte || !arg.isSimple()) + arg !is PtNumber && arg !is PtBool && arg !is PtIdentifier && (arg !is PtMemoryByte || !arg.isSimple()) private val subroutineExtrasCache = mutableMapOf() diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 404269aaf..b3b477d26 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -315,6 +315,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A) asmgen.out(" cmp #${arg2.number.toInt()}") } + is PtBool -> { + asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A) + asmgen.out(" cmp #${arg2.asInt()}") + } is PtMemoryByte -> { if(arg2.address is PtNumber) { asmgen.assignExpressionToRegister(arg1, RegisterOrPair.A) @@ -343,6 +347,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, cmp ${asmgen.asmVariableName(arg2)} +""") } + is PtBool -> TODO("word compare against bool") is PtNumber -> { asmgen.assignExpressionToRegister(arg1, RegisterOrPair.AY) asmgen.out(""" diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt index df6d9ed9a..515445b91 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt @@ -359,7 +359,7 @@ $loopLabel lda ${65535.toHex()} ; modified bne $loopLabel $endLabel""") } - DataType.ARRAY_UB, DataType.ARRAY_B -> { + DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_BOOL -> { val indexVar = asmgen.makeLabel("for_index") asmgen.out(""" ldy #0 diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index 1c579c43d..524031a91 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -16,8 +16,8 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as } internal fun optimizeIntArgsViaRegisters(sub: PtSub) = - (sub.parameters.size==1 && sub.parameters[0].type in IntegerDatatypes) - || (sub.parameters.size==2 && sub.parameters[0].type in ByteDatatypes && sub.parameters[1].type in ByteDatatypes) + (sub.parameters.size==1 && sub.parameters[0].type in IntegerDatatypesWithBoolean) + || (sub.parameters.size==2 && sub.parameters[0].type in ByteDatatypesWithBoolean && sub.parameters[1].type in ByteDatatypesWithBoolean) internal fun translateFunctionCall(call: PtFunctionCall) { // Output only the code to set up the parameters and perform the actual call @@ -84,6 +84,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as is PtMachineRegister -> false is PtMemoryByte -> return usesOtherRegistersWhileEvaluating(arg.address) is PtNumber -> false + is PtBool -> false else -> true } } @@ -152,7 +153,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as } if (statusflag!=null) { if(requiredDt!=value.type) - throw AssemblyError("for statusflag, byte value is required") + throw AssemblyError("for statusflag, byte or bool value is required") if (statusflag == Statusflag.Pc) { // this boolean param needs to be set last, right before the jsr // for now, this is already enforced on the subroutine definition by the Ast Checker @@ -161,6 +162,9 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as val carrySet = value.number.toInt() != 0 asmgen.out(if(carrySet) " sec" else " clc") } + is PtBool -> { + asmgen.out(if(value.value) " sec" else " clc") + } is PtIdentifier -> { val sourceName = asmgen.asmVariableName(value) // note: cannot use X register here to store A because it might be used for other arguments diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index 779e5bcff..b087145d9 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -404,7 +404,7 @@ internal class ProgramAndVarsGen( if(sub.parameters.size==1) { val dt = sub.parameters[0].type val target = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, dt, sub, sub.parameters[0].position, variableAsmName = sub.parameters[0].name) - if(dt in ByteDatatypes) + if(dt in ByteDatatypesWithBoolean) asmgen.assignRegister(RegisterOrPair.A, target) else asmgen.assignRegister(RegisterOrPair.AY, target) @@ -604,7 +604,7 @@ internal class ProgramAndVarsGen( private fun uninitializedVariable2asm(variable: StStaticVariable) { when (variable.dt) { - DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ?") + DataType.BOOL, DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ?") DataType.BYTE -> asmgen.out("${variable.name}\t.char ?") DataType.UWORD -> asmgen.out("${variable.name}\t.word ?") DataType.WORD -> asmgen.out("${variable.name}\t.sint ?") @@ -634,6 +634,7 @@ internal class ProgramAndVarsGen( } else 0 when (variable.dt) { + DataType.BOOL -> TODO("bool var to asm") DataType.UBYTE -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}") DataType.BYTE -> asmgen.out("${variable.name}\t.char $initialValue") DataType.UWORD -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}") @@ -658,7 +659,7 @@ internal class ProgramAndVarsGen( private fun arrayVariable2asm(varname: String, dt: DataType, value: StArray?, orNumberOfZeros: Int?) { when(dt) { - DataType.ARRAY_UB -> { + DataType.ARRAY_UB, DataType.ARRAY_BOOL -> { val data = makeArrayFillDataUnsigned(dt, value, orNumberOfZeros) if (data.size <= 16) asmgen.out("$varname\t.byte ${data.joinToString()}") @@ -763,6 +764,16 @@ internal class ProgramAndVarsGen( private fun makeArrayFillDataUnsigned(dt: DataType, value: StArray?, orNumberOfZeros: Int?): List { val array = value ?: zeroFilledArray(orNumberOfZeros!!) return when (dt) { + DataType.ARRAY_BOOL -> + // byte array can never contain pointer-to types, so treat values as all integers + array.map { + if(it.boolean!=null) + if(it.boolean==true) "1" else "0" + else { + val number = it.number!! + if(number==0.0) "0" else "1" + } + } DataType.ARRAY_UB -> // byte array can never contain pointer-to types, so treat values as all integers array.map { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt index af9dab3eb..caf6a5247 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt @@ -18,8 +18,8 @@ internal class AnyExprAsmGen( ) { fun assignAnyExpressionUsingStack(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { when(expr.type) { - in ByteDatatypes -> { - if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) + in ByteDatatypesWithBoolean -> { + if(expr.left.type in ByteDatatypesWithBoolean && expr.right.type in ByteDatatypesWithBoolean) return assignByteBinExpr(expr, assign) if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) { require(expr.operator in ComparisonOperators) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt index 0731e91fc..cb0dfb687 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt @@ -14,6 +14,7 @@ internal enum class TargetStorageKind { } internal enum class SourceStorageKind { + LITERALBOOLEAN, LITERALNUMBER, VARIABLE, ARRAY, @@ -133,6 +134,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind, val memory: PtMemoryByte? = null, val register: RegisterOrPair? = null, val number: PtNumber? = null, + val boolean: PtBool? = null, val expression: PtExpression? = null ) { @@ -147,6 +149,9 @@ internal class AsmAssignSource(val kind: SourceStorageKind, val cv = value as? PtNumber if(cv!=null) return AsmAssignSource(SourceStorageKind.LITERALNUMBER, program, asmgen, cv.type, number = cv) + val bv = value as? PtBool + if(bv!=null) + return AsmAssignSource(SourceStorageKind.LITERALBOOLEAN, program, asmgen, DataType.BOOL, boolean = bv) return when(value) { // checked above: is PtNumber -> throw AssemblyError("should have been constant value") @@ -194,7 +199,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind, // allow some signed/unsigned relaxations fun withAdjustedDt(newType: DataType) = - AsmAssignSource(kind, program, asmgen, newType, variableAsmName, array, memory, register, number, expression) + AsmAssignSource(kind, program, asmgen, newType, variableAsmName, array, memory, register, number, boolean, expression) if(target.datatype!=datatype) { if(target.datatype in ByteDatatypes && datatype in ByteDatatypes) { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index a97de72e4..bfa920689 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -33,6 +33,16 @@ internal class AssignmentAsmGen(private val program: PtProgram, fun translateNormalAssignment(assign: AsmAssignment, scope: IPtSubroutine?) { when(assign.source.kind) { + SourceStorageKind.LITERALBOOLEAN -> { + // simple case: assign a constant number + val num = assign.source.boolean!!.asInt() + when (assign.target.datatype) { + DataType.BOOL, DataType.UBYTE, DataType.BYTE -> assignConstantByte(assign.target, num) + DataType.UWORD, DataType.WORD -> assignConstantWord(assign.target, num) + DataType.FLOAT -> assignConstantFloat(assign.target, num.toDouble()) + else -> throw AssemblyError("weird numval type") + } + } SourceStorageKind.LITERALNUMBER -> { // simple case: assign a constant number val num = assign.source.number!!.number diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index d63370121..c479ad350 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -18,13 +18,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, val a2 = AsmAssignment(assign.source, assign.target, assign.memsizer, assign.position) assignmentAsmGen.inplaceNegate(a2, false, scope) } - "~" -> { + "~", "not" -> { val a2 = AsmAssignment(assign.source, assign.target, assign.memsizer, assign.position) assignmentAsmGen.inplaceInvert(a2, scope) } "+" -> { /* is a nop */ } else -> { - require(assign.operator in ComparisonOperators || assign.operator.length>=2) { "invalid aug assign operator ${assign.operator}" } augmentedAssignExpr(assign) } } @@ -64,11 +63,15 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, fun regName(v: AsmAssignSource) = "cx16.${v.register!!.name.lowercase()}" + if(value.kind==SourceStorageKind.LITERALBOOLEAN) + TODO("inplace modification literalboolean") + when (target.kind) { TargetStorageKind.VARIABLE -> { when (target.datatype) { - in ByteDatatypes -> { + in ByteDatatypesWithBoolean -> { when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationByteVariableWithLiteralval(target.asmVarname, target.datatype, operator, value.boolean!!.asInt()) SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(target.asmVarname, target.datatype, operator, value.number!!.number.toInt()) SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(target.asmVarname, target.datatype, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(target.asmVarname, target.datatype, operator, regName(value)) @@ -87,6 +90,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, in WordDatatypes -> { val block = target.origAstTarget?.definingBlock() when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationWordWithLiteralval(target.asmVarname, target.datatype, operator, value.boolean!!.asInt(), block) SourceStorageKind.LITERALNUMBER -> inplacemodificationWordWithLiteralval(target.asmVarname, target.datatype, operator, value.number!!.number.toInt(), block) SourceStorageKind.VARIABLE -> inplacemodificationWordWithVariable(target.asmVarname, target.datatype, operator, value.asmVarname, value.datatype, block) SourceStorageKind.REGISTER -> inplacemodificationWordWithVariable(target.asmVarname, target.datatype, operator, regName(value), value.datatype, block) @@ -105,6 +109,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, } DataType.FLOAT -> { when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.boolean!!.asInt().toDouble()) SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(target.asmVarname, operator, value.number!!.number) SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(target.asmVarname, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(target.asmVarname, operator, regName(value)) @@ -129,6 +134,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, is PtNumber -> { val addr = (memory.address as PtNumber).number.toInt() when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationByteVariableWithLiteralval(addr.toHex(), DataType.UBYTE, operator, value.boolean!!.asInt()) SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(addr.toHex(), DataType.UBYTE, operator, value.number!!.number.toInt()) SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(addr.toHex(), DataType.UBYTE, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(addr.toHex(), DataType.UBYTE, operator, regName(value)) @@ -147,6 +153,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, is PtIdentifier -> { val pointer = memory.address as PtIdentifier when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.boolean!!.asInt()) SourceStorageKind.LITERALNUMBER -> inplacemodificationBytePointerWithLiteralval(pointer, operator, value.number!!.number.toInt()) SourceStorageKind.VARIABLE -> inplacemodificationBytePointerWithVariable(pointer, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationBytePointerWithVariable(pointer, operator, regName(value)) @@ -170,6 +177,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, asmgen.saveRegisterStack(CpuRegister.Y, true) asmgen.out(" jsr prog8_lib.read_byte_from_address_in_AY_into_A") when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> { + inplacemodificationRegisterAwithVariable(operator, "#${value.boolean!!.asInt()}", false) + asmgen.out(" tax") + } SourceStorageKind.LITERALNUMBER -> { inplacemodificationRegisterAwithVariable(operator, "#${value.number!!.number.toInt()}", false) asmgen.out(" tax") @@ -231,6 +242,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, when (target.datatype) { in ByteDatatypes -> { when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.boolean!!.asInt()) SourceStorageKind.LITERALNUMBER -> inplacemodificationByteVariableWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt()) SourceStorageKind.VARIABLE -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationByteVariableWithVariable(targetVarName, target.datatype, operator, regName(value)) @@ -250,6 +262,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, in WordDatatypes -> { val block = target.origAstTarget?.definingBlock() when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationWordWithLiteralval(targetVarName, target.datatype, operator, value.boolean!!.asInt(), block) SourceStorageKind.LITERALNUMBER -> inplacemodificationWordWithLiteralval(targetVarName, target.datatype, operator, value.number!!.number.toInt(), block) SourceStorageKind.VARIABLE -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, value.asmVarname, value.datatype, block) SourceStorageKind.REGISTER -> inplacemodificationWordWithVariable(targetVarName, target.datatype, operator, regName(value), value.datatype, block) @@ -268,6 +281,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, DataType.FLOAT -> { when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.boolean!!.asInt().toDouble()) SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.number!!.number) SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(targetVarName, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(targetVarName, operator, regName(value)) @@ -304,6 +318,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, asmgen.saveRegisterStack(CpuRegister.Y, false) asmgen.out(" lda ${target.array.variable.name},y") when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> { + inplacemodificationRegisterAwithVariable(operator, "#${value.boolean!!.asInt()}", target.datatype in SignedDatatypes) + asmgen.restoreRegisterStack(CpuRegister.Y, true) + } SourceStorageKind.LITERALNUMBER -> { inplacemodificationRegisterAwithVariable(operator, "#${value.number!!.number.toInt()}", target.datatype in SignedDatatypes) asmgen.restoreRegisterStack(CpuRegister.Y, true) @@ -363,6 +381,14 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, } val block = target.origAstTarget?.definingBlock() when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> { + val number = value.boolean!!.asInt() + if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) { + asmgen.out(" sta P8ZP_SCRATCH_W1 | stx P8ZP_SCRATCH_W1+1") + inplacemodificationWordWithLiteralval("P8ZP_SCRATCH_W1", target.datatype, operator, number, block) + asmgen.out(" lda P8ZP_SCRATCH_W1 | ldx P8ZP_SCRATCH_W1+1") + } + } SourceStorageKind.LITERALNUMBER -> { val number = value.number!!.number.toInt() if(!inplacemodificationRegisterAXwithLiteralval(operator, number)) { @@ -446,6 +472,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, // calculate on tempvar when(value.kind) { + SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.boolean!!.asInt().toDouble()) SourceStorageKind.LITERALNUMBER -> inplacemodificationFloatWithLiteralval(tempvar, operator, value.number!!.number) SourceStorageKind.VARIABLE -> inplacemodificationFloatWithVariable(tempvar, operator, value.asmVarname) SourceStorageKind.REGISTER -> inplacemodificationFloatWithVariable(tempvar, operator, regName(value)) @@ -953,7 +980,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, + lda #1 +""") } - // pretty uncommon, who's going to assign a comparison boolean expresion to a pointer? + // pretty uncommon, who's going to assign a comparison boolean expression to a pointer? "<", "<=", ">", ">=" -> TODO("byte-var-to-pointer comparisons") else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -1058,7 +1085,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, +""") asmgen.storeAIntoZpPointerVar(sourceName, false) } - // pretty uncommon, who's going to assign a comparison boolean expresion to a pointer?: + // pretty uncommon, who's going to assign a comparison boolean expression to a pointer?: "<", "<=", ">", ">=" -> TODO("byte-litval-to-pointer comparisons") else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -2400,7 +2427,7 @@ $shortcutLabel:""") lda #0 sta $name+1""") } - // pretty uncommon, who's going to assign a comparison boolean expresion to a word var?: + // pretty uncommon, who's going to assign a comparison boolean expression to a word var?: "<", "<=", ">", ">=" -> TODO("word-bytevar-to-var comparisons") else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -2827,7 +2854,7 @@ $shortcutLabel:""") lda #0 sta $name+1""") } - // pretty uncommon, who's going to assign a comparison boolean expresion to a word var?: + // pretty uncommon, who's going to assign a comparison boolean expression to a word var?: "<", "<=", ">", ">=" -> TODO("word-bytevalue-to-var comparisons") else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -2907,7 +2934,7 @@ $shortcutLabel:""") lda #0 sta $name+1""") } - // pretty uncommon, who's going to assign a comparison boolean expresion to a word var?: + // pretty uncommon, who's going to assign a comparison boolean expression to a word var?: "<", "<=", ">", ">=" -> TODO("word-value-to-var comparisons") else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -2947,7 +2974,7 @@ $shortcutLabel:""") jsr floats.FDIV """) } - // pretty uncommon, who's going to assign a comparison boolean expresion to a float var: + // pretty uncommon, who's going to assign a comparison boolean expression to a float var: "==" -> TODO("float-value-to-var comparison ==") "!=" -> TODO("float-value-to-var comparison !=") "<", "<=", ">", ">=" -> TODO("float-value-to-var comparisons") @@ -3003,7 +3030,7 @@ $shortcutLabel:""") jsr floats.FDIV """) } - // pretty uncommon, who's going to assign a comparison boolean expresion to a float var: + // pretty uncommon, who's going to assign a comparison boolean expression to a float var: "==" -> { asmgen.out(""" lda #<$name diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 717508563..06d841c1e 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,8 +1,8 @@ TODO ==== -while not cx16.mouse_pos() should give error +merge last 2 codegen files from booleans-tryout branch: AssignmentAsmGen, ExpressionGen (everything else was merged) ConstantFoldingOptimizer (after merging master): after(numLiteral..) : check that cast to/from BOOL is not done?? @@ -29,6 +29,7 @@ ok . type error for bool[3] derp = 99 and also for init value [1,0,1] ok . while booleanvar==42 and do..until booleanvar==42 should give type error ok . while not should give type error ok . while not should give type error +ok . while not cx16.mouse_pos() should give condition type error ok . while boolean should produce identical code as while integer!=0 ok . while not boolvar -> can we get rid of the cmp? (6502 only?) ok . if someint==0 / ==1 should stil produce good asm same as what it used to be with if not someint/if someint