From 0c81b32cac759d3fa70a6d38045bc8469191a4d9 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 25 Mar 2023 22:43:38 +0100 Subject: [PATCH 1/6] todo --- docs/source/todo.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 954526c3a..fbaa1af74 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,15 +1,9 @@ TODO ==== -replace RPN by something that actually works and is efficient... - For next minor release ^^^^^^^^^^^^^^^^^^^^^^ -- ubyte fits = cx Date: Sun, 26 Mar 2023 04:49:23 +0200 Subject: [PATCH 2/6] new attempt --- codeCore/src/prog8/code/ast/AstExpressions.kt | 8 +- codeCore/src/prog8/code/ast/AstStatements.kt | 13 +- .../src/prog8/codegen/cpu6502/AsmGen.kt | 89 ++++-- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 2 + .../codegen/cpu6502/ExpressionsAsmGen.kt | 2 + .../cpu6502/assignment/AssignmentAsmGen.kt | 8 +- .../assignment/AugmentableAssignmentAsmGen.kt | 292 +++++++++++++++++- .../codegen/experimental/ExperiCodeGen.kt | 5 - .../codegen/intermediate/AssignmentGen.kt | 4 +- .../codegen/intermediate/ExpressionGen.kt | 1 + .../prog8/codegen/intermediate/IRCodeGen.kt | 1 + .../src/prog8/codegen/vm/VmCodeGen.kt | 7 - compiler/res/prog8lib/c128/floats.asm | 2 +- compiler/src/prog8/compiler/Compiler.kt | 169 +++++++++- .../compiler/astprocessing/AstChecker.kt | 6 +- ...NotExpressionAndIfComparisonExprChanger.kt | 2 + examples/test.p8 | 157 ++++++++-- 17 files changed, 686 insertions(+), 82 deletions(-) diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index 6adfea186..aeaeff577 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -180,7 +180,13 @@ class PtFunctionCall(val name: String, } -class PtIdentifier(val name: String, type: DataType, position: Position) : PtExpression(type, position) +class PtIdentifier(val name: String, type: DataType, position: Position) : PtExpression(type, position) { + override fun toString(): String { + return "[PtIdentifier:$name $type $position]" + } + + fun copy() = PtIdentifier(name, type, position) +} class PtMemoryByte(position: Position) : PtExpression(DataType.UBYTE, position) { diff --git a/codeCore/src/prog8/code/ast/AstStatements.kt b/codeCore/src/prog8/code/ast/AstStatements.kt index 8245e7910..4720b9190 100644 --- a/codeCore/src/prog8/code/ast/AstStatements.kt +++ b/codeCore/src/prog8/code/ast/AstStatements.kt @@ -38,20 +38,17 @@ class PtSub( class PtSubroutineParameter(name: String, val type: DataType, position: Position): PtNamedNode(name, position) -class PtAssignment(position: Position) : PtNode(position) { +sealed interface IPtAssignment { + val children: MutableList val target: PtAssignTarget get() = children[0] as PtAssignTarget val value: PtExpression get() = children[1] as PtExpression } +class PtAssignment(position: Position) : PtNode(position), IPtAssignment -class PtAugmentedAssign(val operator: String, position: Position) : PtNode(position) { - val target: PtAssignTarget - get() = children[0] as PtAssignTarget - val value: PtExpression - get() = children[1] as PtExpression -} +class PtAugmentedAssign(val operator: String, position: Position) : PtNode(position), IPtAssignment class PtAssignTarget(position: Position) : PtNode(position) { @@ -95,7 +92,7 @@ class PtForLoop(position: Position) : PtNode(position) { class PtIfElse(position: Position) : PtNode(position) { - val condition: PtExpression // either PtRpn or PtBinaryExpression + val condition: PtExpression get() = children[0] as PtExpression val ifScope: PtNodeGroup get() = children[1] as PtNodeGroup diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 5d98a1130..157293f6b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -21,13 +21,6 @@ class AsmGen6502: ICodeGeneratorBackend { options: CompilationOptions, errors: IErrorReporter ): IAssemblyProgram? { - if(options.useNewExprCode) { - // TODO("transform BinExprs?") - // errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY) - } - - // printAst(program, true) { println(it) } - val asmgen = AsmGen6502Internal(program, symbolTable, options, errors) return asmgen.compileToAssembly() } @@ -551,28 +544,74 @@ class AsmGen6502Internal ( } private fun translate(stmt: PtIfElse) { - val condition = stmt.condition as PtBinaryExpression - requireComparisonExpression(condition) // IfStatement: condition must be of form 'x ' - if (stmt.elseScope.children.isEmpty()) { - val jump = stmt.ifScope.children.singleOrNull() - if (jump is PtJump) { - translateCompareAndJumpIfTrue(condition, jump) + val condition = stmt.condition as? PtBinaryExpression + if(condition!=null) { + require(!options.useNewExprCode) + requireComparisonExpression(condition) // IfStatement: condition must be of form 'x ' + if (stmt.elseScope.children.isEmpty()) { + val jump = stmt.ifScope.children.singleOrNull() + if (jump is PtJump) { + translateCompareAndJumpIfTrue(condition, jump) + } else { + val endLabel = makeLabel("if_end") + translateCompareAndJumpIfFalse(condition, endLabel) + translate(stmt.ifScope) + out(endLabel) + } } else { + // both true and else parts + val elseLabel = makeLabel("if_else") val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalse(condition, endLabel) + translateCompareAndJumpIfFalse(condition, elseLabel) translate(stmt.ifScope) + jmp(endLabel) + out(elseLabel) + translate(stmt.elseScope) out(endLabel) } } else { - // both true and else parts - val elseLabel = makeLabel("if_else") - val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalse(condition, elseLabel) - translate(stmt.ifScope) - jmp(endLabel) - out(elseLabel) - translate(stmt.elseScope) - out(endLabel) + // condition is a simple expression "if X" --> "if X!=0" + val zero = PtNumber(DataType.UBYTE,0.0, stmt.position) + val leftConst = stmt.condition as? PtNumber + if (stmt.elseScope.children.isEmpty()) { + val jump = stmt.ifScope.children.singleOrNull() + if (jump is PtJump) { + val label = when { + jump.generatedLabel!=null -> jump.generatedLabel!! + jump.identifier!=null -> asmSymbolName(jump.identifier!!) + jump.address!=null -> jump.address!!.toHex() + else -> throw AssemblyError("weird jump") + } + when(stmt.condition.type) { + in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, label) + in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, label) + else -> throw AssemblyError("weird condition dt") + } + } else { + val endLabel = makeLabel("if_end") + when(stmt.condition.type) { + in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) + in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) + else -> throw AssemblyError("weird condition dt") + } + translate(stmt.ifScope) + out(endLabel) + } + } else { + // both true and else parts + val elseLabel = makeLabel("if_else") + val endLabel = makeLabel("if_end") + when(stmt.condition.type) { + in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, elseLabel) + in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, elseLabel) + else -> throw AssemblyError("weird condition dt") + } + translate(stmt.ifScope) + jmp(endLabel) + out(elseLabel) + translate(stmt.elseScope) + out(endLabel) + } } } @@ -740,7 +779,7 @@ $repeatLabel lda $counterVar } val isNested = parent is PtRepeatLoop - if(!isNested && !options.useNewExprCode) { + if(!isNested) { // we can re-use a counter var from the subroutine if it already has one for that datatype val existingVar = asmInfo.extraVars.firstOrNull { it.first==dt && it.second.endsWith("counter") } if(existingVar!=null) { @@ -987,6 +1026,7 @@ $repeatLabel lda $counterVar val operator: String if (pointerOffsetExpr is PtBinaryExpression) { + require(!options.useNewExprCode) operator = pointerOffsetExpr.operator left = pointerOffsetExpr.left right = pointerOffsetExpr.right @@ -2853,6 +2893,7 @@ $repeatLabel lda $counterVar out(" sta P8ESTACK_LO,x | dex") } is PtBinaryExpression -> { + require(!options.useNewExprCode) val addrExpr = expr.address as PtBinaryExpression if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) { if(pushResultOnEstack) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 79b6f3d2d..e49456fce 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -662,6 +662,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } } is PtBinaryExpression -> { + require(!asmgen.options.useNewExprCode) val result = asmgen.pointerViaIndexRegisterPossible(addrExpr) val pointer = result?.first as? PtIdentifier if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) { @@ -724,6 +725,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } else fallback() } is PtBinaryExpression -> { + require(!asmgen.options.useNewExprCode) val result = asmgen.pointerViaIndexRegisterPossible(addrExpr) val pointer = result?.first as? PtIdentifier if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt index 0e80ba5cc..1b74cb6aa 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt @@ -245,6 +245,8 @@ internal class ExpressionsAsmGen(private val program: PtProgram, } private fun translateExpression(expr: PtBinaryExpression) { + require(!asmgen.options.useNewExprCode) + // Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED! if(translateSomewhatOptimized(expr.left, expr.operator, expr.right)) return diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 493c49433..8b56e594b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -147,6 +147,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, assignMemoryByte(assign.target, null, value.address as PtIdentifier) } is PtBinaryExpression -> { + require(!asmgen.options.useNewExprCode) val addrExpr = value.address as PtBinaryExpression if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) { assignRegisterByte(assign.target, CpuRegister.A) @@ -301,6 +302,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, assignRegisterByte(assign.target, CpuRegister.A) } is PtBinaryExpression -> { + require(!asmgen.options.useNewExprCode) if(!attemptAssignOptimizedBinexpr(value, assign)) { // All remaining binary expressions just evaluate via the stack for now. // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, @@ -346,6 +348,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { + require(!asmgen.options.useNewExprCode) if(expr.operator in ComparisonOperators) { if(expr.right.asConstInteger() == 0) { if(expr.operator == "==" || expr.operator=="!=") { @@ -728,6 +731,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } private fun attemptAssignToByteCompareZero(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { + require(!asmgen.options.useNewExprCode) when (expr.operator) { "==" -> { when(val dt = expr.left.type) { @@ -907,6 +911,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, assignMemoryByteIntoWord(target, null, value.address as PtIdentifier) } is PtBinaryExpression -> { + require(!asmgen.options.useNewExprCode) val addrExpr = value.address as PtBinaryExpression if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) { asmgen.out(" ldy #0") @@ -2519,7 +2524,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } } - private fun assignConstantFloat(target: AsmAssignTarget, float: Double) { + internal fun assignConstantFloat(target: AsmAssignTarget, float: Double) { if (float == 0.0) { // optimized case for float zero when(target.kind) { @@ -2829,6 +2834,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.storeAIntoPointerVar(addressExpr) } addressExpr is PtBinaryExpression -> { + require(!asmgen.options.useNewExprCode) if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true)) storeViaExprEval() } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index fed3661b9..2cd2c7f0d 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -1319,8 +1319,174 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, lda #0 sta $name+1""") } - // pretty uncommon, who's going to assign a comparison boolean expresion to a word var?: - "<", "<=", ">", ">=" -> TODO("word-litval-to-var comparisons") + "<" -> { + if(dt==DataType.UWORD) { + asmgen.out(""" + lda $name+1 + cmp #>$value + bcc ++ + bne + + lda $name + cmp #<$value + bcc ++ ++ lda #0 ; false + sta $name + sta $name+1 + beq ++ ++ lda #1 ; true + sta $name + lda #0 + sta $name+1 ++""") + } + else { + // signed + asmgen.out(""" + lda $name + cmp #<$value + lda $name+1 + sbc #>$value + bvc + + eor #$80 ++ bmi + + lda #0 + sta $name + sta $name+1 + beq ++ ++ lda #1 ; true + sta $name + lda #0 + sta $name+1 ++""") + } + } + "<=" -> { + if(dt==DataType.UWORD) { + asmgen.out(""" + lda $name+1 + cmp #>$value + beq + + bcc ++ +- lda #0 ; false + sta $name + sta $name+1 + beq +++ ++ lda $name ; next + cmp #<$value + bcc + + bne - ++ lda #1 ; true + sta $name + lda #0 + sta $name+1 ++""") + } + else { + // signed + asmgen.out(""" + lda #<$value + cmp $name + lda #>$value + sbc $name+1 + bvc + + eor #$80 ++ bpl + + lda #0 + sta $name + sta $name+1 + beq ++ ++ lda #1 + sta $name + lda #0 + sta $name+1 ++""") + } + } + ">" -> { + // word > value --> value < word + if(dt==DataType.UWORD) { + asmgen.out(""" + lda #>$value + cmp $name+1 + bcc ++ + bne + + lda #<$value + cmp $name + bcc ++ ++ lda #0 ; false + sta $name + sta $name+1 + beq ++ ++ lda #1 ; true + sta $name + lda #0 + sta $name+1 ++""") + } + else { + // signed + asmgen.out(""" + lda #<$value + cmp $name + lda #>$value + sbc $name+1 + bvc + + eor #$80 ++ bmi + + lda #0 + sta $name + sta $name+1 + beq ++ ++ lda #1 ; true + sta $name + lda #0 + sta $name+1 ++""") + } + } + ">=" -> { + // word >= value --> value <= word + if(dt==DataType.UWORD) { + asmgen.out(""" + lda #>$value + cmp $name+1 + beq + + bcc ++ +- lda #0 ; false + sta $name + sta $name+1 + beq +++ ++ lda #<$value ; next + cmp $name + bcc + + bne - ++ lda #1 ; true + sta $name + lda #0 + sta $name+1 ++""") + } + else { + // signed + asmgen.out(""" + lda $name + cmp #<$value + lda $name+1 + sbc #>$value + bvc + + eor #$80 ++ bpl + + lda #0 + sta $name + sta $name+1 + beq ++ ++ lda #1 + sta $name + lda #0 + sta $name+1 ++""") + } + } else -> throw AssemblyError("invalid operator for in-place modification $operator") } } @@ -2129,8 +2295,126 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, jsr floats.FDIV """) } - // pretty uncommon, who's going to assign a comparison boolean expresion to a float var: - "==", "!=", "<", "<=", ">", ">=" -> TODO("float-litval-to-var comparisons") + "==" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda #<$constValueName + ldy #>$constValueName + jsr floats.vars_equal_f + bne +""") + val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) + assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) + asmgen.out(""" + jmp ++ ++""") + assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) + asmgen.out("+") + asmgen.restoreRegisterLocal(CpuRegister.X) + return + } + "!=" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda #<$constValueName + ldy #>$constValueName + jsr floats.vars_equal_f + beq +""") + val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) + assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) + asmgen.out(""" + jmp ++ ++""") + assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) + asmgen.out("+") + asmgen.restoreRegisterLocal(CpuRegister.X) + return + } + "<" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$constValueName + ldy #>$constValueName + jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than + cmp #0 + bmi +""") + val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) + assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) + asmgen.out(""" + jmp ++ ++""") + assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) + asmgen.out("+") + asmgen.restoreRegisterLocal(CpuRegister.X) + return + } + "<=" -> { + asmgen.out(""" + lda #<$constValueName + ldy #>$constValueName + jsr floats.MOVFM + lda #<$name + ldy #>$name + jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than + cmp #0 + bpl +""") + val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) + assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) + asmgen.out(""" + jmp ++ ++""") + assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) + asmgen.out("+") + asmgen.restoreRegisterLocal(CpuRegister.X) + return + } + ">" -> { + asmgen.out(""" + lda #<$constValueName + ldy #>$constValueName + jsr floats.MOVFM + lda #<$name + ldy #>$name + jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than + cmp #0 + bmi +""") + val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) + assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) + asmgen.out(""" + jmp ++ ++""") + assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) + asmgen.out("+") + asmgen.restoreRegisterLocal(CpuRegister.X) + return + } + ">=" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$constValueName + ldy #>$constValueName + jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than + cmp #0 + bpl +""") + val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) + assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) + asmgen.out(""" + jmp ++ ++""") + assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) + asmgen.out("+") + asmgen.restoreRegisterLocal(CpuRegister.X) + return + } else -> throw AssemblyError("invalid operator for in-place float modification $operator") } // store Fac1 back into memory diff --git a/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt b/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt index a2782af40..2bf4c82b6 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/ExperiCodeGen.kt @@ -14,11 +14,6 @@ class ExperiCodeGen: ICodeGeneratorBackend { errors: IErrorReporter ): IAssemblyProgram? { - if(options.useNewExprCode) { - // TODO("transform BinExprs?") - // errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY) - } - // you could write a code generator directly on the PtProgram AST, // but you can also use the Intermediate Representation to build a codegen on: val irCodeGen = IRCodeGen(program, symbolTable, options, errors) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index f76fe32dd..6fc9c81f8 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -93,7 +93,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express } else { require(origAssign.operator.endsWith('=')) if(codeGen.options.useNewExprCode) { - TODO("use something else than a BinExpr?") + TODO("use something else than a BinExpr") } else { value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position) val left: PtExpression = origAssign.target.children.single() as PtExpression @@ -268,7 +268,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express } else { val mult : PtExpression if(codeGen.options.useNewExprCode) { - TODO("use something else than a BinExpr?") + TODO("use something else than a BinExpr") } else { mult = PtBinaryExpression("*", DataType.UBYTE, array.position) mult.children += array.index diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index edfa803fd..177b79486 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -320,6 +320,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } private fun translate(binExpr: PtBinaryExpression): ExpressionCodeResult { + require(!codeGen.options.useNewExprCode) val vmDt = codeGen.irType(binExpr.left.type) val signed = binExpr.left.type in SignedDatatypes return when(binExpr.operator) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 80b89036b..fa1ccf7db 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -899,6 +899,7 @@ class IRCodeGen( val goto = ifElse.ifScope.children.firstOrNull() as? PtJump when (condition) { is PtBinaryExpression -> { + require(!options.useNewExprCode) if(condition.operator !in ComparisonOperators) throw AssemblyError("if condition should only be a binary comparison expression") diff --git a/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt index 5b1995599..0718ae7a6 100644 --- a/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/vm/VmCodeGen.kt @@ -14,13 +14,6 @@ class VmCodeGen: ICodeGeneratorBackend { options: CompilationOptions, errors: IErrorReporter ): IAssemblyProgram? { - - if(options.useNewExprCode) { - // TODO("transform BinExprs?") - // errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY) - } - - val irCodeGen = IRCodeGen(program, symbolTable, options, errors) val irProgram = irCodeGen.generate() return VmAssemblyProgram(irProgram.name, irProgram) diff --git a/compiler/res/prog8lib/c128/floats.asm b/compiler/res/prog8lib/c128/floats.asm index 92f6afc0f..cd60909d9 100644 --- a/compiler/res/prog8lib/c128/floats.asm +++ b/compiler/res/prog8lib/c128/floats.asm @@ -251,7 +251,7 @@ pop_float_fac1 .proc .pend copy_float .proc - ; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_ZPWORD1, + ; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_W1, ; into the 5 bytes pointed to by A/Y. Clobbers A,Y. sta _target+1 sty _target+2 diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index d7d45b277..82b2fd847 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -8,7 +8,7 @@ import prog8.ast.expressions.Expression import prog8.ast.expressions.NumericLiteral import prog8.ast.statements.Directive import prog8.code.SymbolTableMaker -import prog8.code.ast.PtProgram +import prog8.code.ast.* import prog8.code.core.* import prog8.code.target.* import prog8.codegen.vm.VmCodeGen @@ -409,6 +409,11 @@ private fun createAssemblyAndAssemble(program: PtProgram, else throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}") + if(compilerOptions.useNewExprCode) + transformNewExpressions(program) + + printAst(program, true) { println(it) } + val stMaker = SymbolTableMaker(program, compilerOptions) val symbolTable = stMaker.make() val assembly = asmgen.generate(program, symbolTable, compilerOptions, errors) @@ -420,3 +425,165 @@ private fun createAssemblyAndAssemble(program: PtProgram, false } } + +private fun transformNewExpressions(program: PtProgram) { + val newVariables = mutableMapOf>() + + fun getExprVar(what: String, type: DataType, count: Int, pos: Position, scope: PtSub): PtIdentifier { + val name = "p8p_exprvar_${what}_${count}_${type.toString().lowercase()}" + var subVars = newVariables[scope] + if(subVars==null) { + subVars = mutableListOf() + newVariables[scope] = subVars + } + if(subVars.all { it.name!=name }) { + subVars.add(PtVariable(name, type, ZeropageWish.DONTCARE, null, null, pos)) + } + return PtIdentifier("${scope.scopedName}.$name", type, pos) + } + + fun transformExpr(expr: PtBinaryExpression, postfix: String, depth: Int): Pair> { + // depth first process the expression tree + val scope = expr.definingSub()!! + val assignments = mutableListOf() + + fun transformOperand(node: PtExpression, kind: String): PtNode { + return when(node) { + is PtNumber, is PtIdentifier, is PtArray, is PtString, is PtMachineRegister -> node + is PtBinaryExpression -> { + val (replacement, subAssigns) = transformExpr(node, kind, depth+1) + assignments.addAll(subAssigns) + replacement + } + else -> { + val variable = getExprVar(kind, node.type, depth, node.position, scope) + val assign = PtAssignment(node.position) + val target = PtAssignTarget(variable.position) + target.add(variable) + assign.add(target) + assign.add(node) + assignments.add(assign) + variable + } + } + } + + val newLeft = transformOperand(expr.left,"l") + val newRight = transformOperand(expr.right, "r") + + // process the binexpr + + val resultVar = + if(expr.type == expr.left.type) { + getExprVar(postfix, expr.type, depth, expr.position, scope) + } else { + if(expr.operator in ComparisonOperators && expr.type == DataType.UBYTE) { + // this is very common and should be dealth with correctly; byte==0, word>42 + getExprVar(postfix, expr.left.type, depth, expr.position, scope) + } + else if(expr.left.type in PassByReferenceDatatypes && expr.type==DataType.UBYTE) { + // this is common and should be dealth with correctly; for instance "name"=="irmen" + getExprVar(postfix, expr.left.type, depth, expr.position, scope) + } else { + TODO("expression type differs from left operand type! got ${expr.left.type} expected ${expr.type} ${expr.position}") + } + } + + if(resultVar.name!=(newLeft as? PtIdentifier)?.name) { + // resultvar = left + val assign1 = PtAssignment(newLeft.position) + val target1 = PtAssignTarget(resultVar.position) + target1.add(resultVar) + assign1.add(target1) + assign1.add(newLeft) + assignments.add(assign1) + } + // resultvar {oper}= right + val operator = if(expr.operator in ComparisonOperators) expr.operator else expr.operator+'=' + val assign2 = PtAugmentedAssign(operator, newRight.position) + val target2 = PtAssignTarget(resultVar.position) + target2.add(resultVar.copy()) + assign2.add(target2) + assign2.add(newRight) + assignments.add(assign2) + return Pair(resultVar, assignments) + } + + fun isProperStatement(node: PtNode): Boolean { + return when(node) { + is PtAssignment -> true + is PtAugmentedAssign -> true + is PtBreakpoint -> true + is PtConditionalBranch -> true + is PtForLoop -> true + is PtIfElse -> true + is PtIncludeBinary -> true + is PtInlineAssembly -> true + is PtJump -> true + is PtAsmSub -> true + is PtLabel -> true + is PtSub -> true + is PtVariable -> true + is PtNop -> true + is PtPostIncrDecr -> true + is PtRepeatLoop -> true + is PtReturn -> true + is PtWhen -> true + is PtBuiltinFunctionCall -> node.void + is PtFunctionCall -> node.void + else -> false + } + } + + fun transform(node: PtNode, parent: PtNode, depth: Int) { + if(node is PtBinaryExpression) { + node.children.toTypedArray().forEach { + transform(it, node, depth+1) + } + val (rep, assignments) = transformExpr(node, "l", depth) + var replacement = rep + if(!(rep.type equalsSize node.type)) { + if(rep.type in NumericDatatypes && node.type in ByteDatatypes) { + replacement = PtTypeCast(node.type, node.position) + replacement.add(rep) + } else + TODO("cast replacement type ${rep.type} -> ${node.type}") + } + var idx = parent.children.indexOf(node) + parent.children[idx] = replacement + replacement.parent = parent + // find the statement above which we should insert the assignments + var stmt = node + while(!isProperStatement(stmt)) + stmt = stmt.parent + idx = stmt.parent.children.indexOf(stmt) + assignments.reversed().forEach { + stmt.parent.add(idx, it as PtNode) + } + } else { + node.children.toTypedArray().forEach { child -> transform(child, node, depth+1) } + } + } + + program.allBlocks().forEach { block -> + block.children.toTypedArray().forEach { + transform(it, block, 0) + } + } + + // add the new variables + newVariables.forEach { (sub, vars) -> + vars.forEach { + sub.add(0, it) + } + } + + // extra check to see that all PtBinaryExpressions have been transformed + fun binExprCheck(node: PtNode) { + if(node is PtBinaryExpression) + throw IllegalArgumentException("still got binexpr $node ${node.position}") + node.children.forEach { binExprCheck(it) } + } + binExprCheck(program) +} + diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 7704f3e9c..afee4d908 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -957,7 +957,11 @@ internal class AstChecker(private val program: Program, } } - if(expr.operator !in ComparisonOperators) { + if(expr.operator in ComparisonOperators) { + if(leftDt!=rightDt && !(leftDt in ByteDatatypes && rightDt in ByteDatatypes)) { + throw FatalAstException("got comparison with different operand types: $leftDt ${expr.operator} $rightDt ${expr.position}") + } + } else { if (leftDt == DataType.STR && rightDt == DataType.STR || leftDt in ArrayDatatypes && rightDt in ArrayDatatypes) { // str+str and str*number have already been const evaluated before we get here. errors.err("no computational or logical expressions with strings or arrays are possible", expr.position) diff --git a/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt b/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt index d133fd0cc..4afe580b9 100644 --- a/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/NotExpressionAndIfComparisonExprChanger.kt @@ -109,6 +109,8 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val if(binExpr==null || binExpr.operator !in ComparisonOperators) return noModifications + return noModifications // TODO tijdelijk geen simplify + // Simplify the conditional expression, introduce simple assignments if required. // This is REQUIRED for correct code generation on 6502 because evaluating certain expressions // clobber the handful of temporary variables in the zeropage and leaving everything in one diff --git a/examples/test.p8 b/examples/test.p8 index 793764c0e..37302c67a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,38 +1,141 @@ +%zeropage basicsafe %import textio %import floats -%zeropage basicsafe - -; Draw a mandelbrot in graphics mode (the image will be 256 x 200 pixels). -; NOTE: this will take an eternity to draw on a real c64. A CommanderX16 is a bit faster. -; even in Vice in warp mode (700% speed on my machine) it's slow, but you can see progress - -; Note: this program is compatible with C64 and CX16. main { - sub start() { - float xsquared = 2.0 - float ysquared = 1.9 - uword w = 1 - ubyte h = 0 + sub start() { + byte b = -100 + ubyte ub = 20 + word w = -20000 + uword uw = 2000 + float f = -100 - str name = ".tx2" + txt.print("all 1: ") + txt.print_ub(b == -100) + txt.print_ub(b != -99) + txt.print_ub(b < -99) + txt.print_ub(b <= -100) + txt.print_ub(b > -101) + txt.print_ub(b >= -100) + txt.print_ub(ub ==20) + txt.print_ub(ub !=19) + txt.print_ub(ub <21) + txt.print_ub(ub <=20) + txt.print_ub(ub>19) + txt.print_ub(ub>=20) + txt.spc() + txt.print_ub(w == -20000) + txt.print_ub(w != -19999) + txt.print_ub(w < -19999) + txt.print_ub(w <= -20000) + txt.print_ub(w > -20001) + txt.print_ub(w >= -20000) + txt.print_ub(uw == 2000) + txt.print_ub(uw != 2001) + txt.print_ub(uw < 2001) + txt.print_ub(uw <= 2000) + txt.print_ub(uw > 1999) + txt.print_ub(uw >= 2000) + txt.spc() + txt.print_ub(f == -100.0) + txt.print_ub(f != -99.0) + txt.print_ub(f < -99.0) + txt.print_ub(f <= -100.0) + txt.print_ub(f > -101.0) + txt.print_ub(f >= -100.0) + txt.nl() - if name==".jpg" or name==".txt" or name==".gif" { - txt.print("yes") + txt.print("all 0: ") + txt.print_ub(b == -99) + txt.print_ub(b != -100) + txt.print_ub(b < -100) + txt.print_ub(b <= -101) + txt.print_ub(b > -100) + txt.print_ub(b >= -99) + txt.print_ub(ub ==21) + txt.print_ub(ub !=20) + txt.print_ub(ub <20) + txt.print_ub(ub <=19) + txt.print_ub(ub>20) + txt.print_ub(ub>=21) + txt.spc() + txt.print_ub(w == -20001) + txt.print_ub(w != -20000) + txt.print_ub(w < -20000) + txt.print_ub(w <= -20001) + txt.print_ub(w > -20000) + txt.print_ub(w >= -19999) + txt.print_ub(uw == 1999) + txt.print_ub(uw != 2000) + txt.print_ub(uw < 2000) + txt.print_ub(uw <= 1999) + txt.print_ub(uw > 2000) + txt.print_ub(uw >= 2001) + txt.spc() + txt.print_ub(f == -99.0) + txt.print_ub(f != -100.0) + txt.print_ub(f < -100.0) + txt.print_ub(f <= -101.0) + txt.print_ub(f > -100.0) + txt.print_ub(f >= -99.0) + txt.nl() + + ; TODO ALL OF THE ABOVE BUT WITH A VARIABLE INSTEAD OF A CONST VALUE + + + b = -100 + while b <= -20 + b++ + txt.print_b(b) + txt.print(" -19\n") + b = -100 + while b < -20 + b++ + txt.print_b(b) + txt.print(" -20\n") + + ub = 20 + while ub <= 200 + ub++ + txt.print_ub(ub) + txt.print(" 201\n") + ub = 20 + while ub < 200 + ub++ + txt.print_ub(ub) + txt.print(" 200\n") + + w = -20000 + while w <= -8000 { + w++ } + txt.print_w(w) + txt.print(" -7999\n") + w = -20000 + while w < -8000 { + w++ + } + txt.print_w(w) + txt.print(" -8000\n") -; if w==0 or xsquared+ysquared<4.0 { -; txt.print("yes") -; } + uw = 2000 + while uw <= 8000 { + uw++ + } + txt.print_uw(uw) + txt.print(" 8001\n") + uw = 2000 + while uw < 8000 { + uw++ + } + txt.print_uw(uw) + txt.print(" 8000\n") -; if w==0 { -; txt.print("w=0 ") -; } -; if h==0 { -; txt.print("h=0 ") -; } -; if w==0 or h==0 { -; txt.print(" w or h=0") -; } + f = 0.0 + while f<2.2 { + f+=0.1 + } + floats.print_f(f) + txt.print(" 2.2\n") } } From 729209574e4140466eebb6dc6f3c5ccecb038b9e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 28 Mar 2023 02:14:16 +0200 Subject: [PATCH 3/6] fixing str compares codegen --- .../src/prog8/code/core/BuiltinFunctions.kt | 1 + .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 7 + .../codegen/intermediate/BuiltinFuncGen.kt | 17 ++ compiler/src/prog8/compiler/Compiler.kt | 12 +- .../astprocessing/BeforeAsmAstChanger.kt | 13 + examples/test.p8 | 261 +++++++++--------- 6 files changed, 184 insertions(+), 127 deletions(-) diff --git a/codeCore/src/prog8/code/core/BuiltinFunctions.kt b/codeCore/src/prog8/code/core/BuiltinFunctions.kt index a19a3b219..d189bc43a 100644 --- a/codeCore/src/prog8/code/core/BuiltinFunctions.kt +++ b/codeCore/src/prog8/code/core/BuiltinFunctions.kt @@ -79,6 +79,7 @@ val BuiltinFunctions: Map = mapOf( "reverse" to FSignature(false, listOf(FParam("array", ArrayDatatypes)), null), // cmp returns a status in the carry flag, but not a proper return value "cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypesNoBool), FParam("value2", NumericDatatypesNoBool)), null), + "prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE), "abs" to FSignature(true, listOf(FParam("value", IntegerDatatypesNoBool)), DataType.UWORD), "len" to FSignature(true, listOf(FParam("values", IterableDatatypes)), DataType.UWORD), // normal functions follow: diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index e49456fce..aba769dd2 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -70,12 +70,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, "rrestorex" -> funcRrestoreX() "cmp" -> funcCmp(fcall) "callfar" -> funcCallFar(fcall) + "prog8_lib_stringcompare" -> funcStringCompare(fcall) else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}") } return BuiltinFunctions.getValue(fcall.name).returnType } + private fun funcStringCompare(fcall: PtBuiltinFunctionCall) { + assignAsmGen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_W2", DataType.UWORD) + assignAsmGen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY, false) + asmgen.out(" jsr prog8_lib.strcmp_mem") + } + private fun funcRsave() { if (asmgen.isTargetCpu(CpuType.CPU65c02)) asmgen.out(""" diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index f2b5ba232..898ecc834 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -41,10 +41,27 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "ror" -> funcRolRor(Opcode.ROXR, call) "rol2" -> funcRolRor(Opcode.ROL, call) "ror2" -> funcRolRor(Opcode.ROR, call) + "prog8_lib_stringcompare" -> funcStringCompare(call) else -> throw AssemblyError("missing builtinfunc for ${call.name}") } } + private fun funcStringCompare(call: PtBuiltinFunctionCall): ExpressionCodeResult { +/* + loadm.w r65500,string.compare.st1 + loadm.w r65501,string.compare.st2 + syscall 29 + returnreg.b r0 + */ + val result = mutableListOf() + val left = exprGen.translateExpression(call.args[0]) + val right = exprGen.translateExpression(call.args[1]) + addToResult(result, left, 65500, -1) + addToResult(result, right, 65501, -1) + addInstr(result, IRInstruction(Opcode.SYSCALL, value=IMSyscall.COMPARE_STRINGS.number), null) + return ExpressionCodeResult(result, IRDataType.BYTE, 0, -1) + } + private fun funcCmp(call: PtBuiltinFunctionCall): ExpressionCodeResult { val result = mutableListOf() val leftTr = exprGen.translateExpression(call.args[0]) diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 82b2fd847..bb58ae311 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -477,13 +477,17 @@ private fun transformNewExpressions(program: PtProgram) { if(expr.type == expr.left.type) { getExprVar(postfix, expr.type, depth, expr.position, scope) } else { - if(expr.operator in ComparisonOperators && expr.type == DataType.UBYTE) { + if(expr.operator in ComparisonOperators && expr.type in ByteDatatypes) { // this is very common and should be dealth with correctly; byte==0, word>42 - getExprVar(postfix, expr.left.type, depth, expr.position, scope) + val varType = if(expr.left.type in PassByReferenceDatatypes) DataType.UWORD else expr.left.type + getExprVar(postfix, varType, depth, expr.position, scope) } else if(expr.left.type in PassByReferenceDatatypes && expr.type==DataType.UBYTE) { - // this is common and should be dealth with correctly; for instance "name"=="irmen" - getExprVar(postfix, expr.left.type, depth, expr.position, scope) + // this is common and should be dealth with correctly; for instance "name"=="john" + val varType = if (expr.left.type in PassByReferenceDatatypes) DataType.UWORD else expr.left.type + getExprVar(postfix, varType, depth, expr.position, scope) + } else if(expr.left.type equalsSize expr.type) { + getExprVar(postfix, expr.type, depth, expr.position, scope) } else { TODO("expression type differs from left operand type! got ${expr.left.type} expected ${expr.type} ${expr.position}") } diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt index bcbc62e23..79dca48b1 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt @@ -36,6 +36,19 @@ internal class BeforeAsmAstChanger(val program: Program, return noModifications } + override fun after(expr: BinaryExpression, parent: Node): Iterable { + if(expr.operator in ComparisonOperators && expr.left.inferType(program) istype DataType.STR && expr.right.inferType(program) istype DataType.STR) { + // replace string comparison expressions with calls to string.compare() + val stringCompare = BuiltinFunctionCall( + IdentifierReference(listOf("prog8_lib_stringcompare"), expr.position), + mutableListOf(expr.left.copy(), expr.right.copy()), expr.position) + val zero = NumericLiteral.optimalInteger(0, expr.position) + val comparison = BinaryExpression(stringCompare, expr.operator, zero, expr.position) + return listOf(IAstModification.ReplaceNode(expr, comparison, parent)) + } + return noModifications + } + override fun after(decl: VarDecl, parent: Node): Iterable { if (decl.type == VarDeclType.VAR && decl.value != null && decl.datatype in NumericDatatypes) throw InternalCompilerException("vardecls for variables, with initial numerical value, should have been rewritten as plain vardecl + assignment $decl") diff --git a/examples/test.p8 b/examples/test.p8 index 37302c67a..ac1286195 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,6 +1,7 @@ %zeropage basicsafe %import textio %import floats +%import string main { sub start() { @@ -9,133 +10,147 @@ main { word w = -20000 uword uw = 2000 float f = -100 + str name="john" - txt.print("all 1: ") - txt.print_ub(b == -100) - txt.print_ub(b != -99) - txt.print_ub(b < -99) - txt.print_ub(b <= -100) - txt.print_ub(b > -101) - txt.print_ub(b >= -100) - txt.print_ub(ub ==20) - txt.print_ub(ub !=19) - txt.print_ub(ub <21) - txt.print_ub(ub <=20) - txt.print_ub(ub>19) - txt.print_ub(ub>=20) - txt.spc() - txt.print_ub(w == -20000) - txt.print_ub(w != -19999) - txt.print_ub(w < -19999) - txt.print_ub(w <= -20000) - txt.print_ub(w > -20001) - txt.print_ub(w >= -20000) - txt.print_ub(uw == 2000) - txt.print_ub(uw != 2001) - txt.print_ub(uw < 2001) - txt.print_ub(uw <= 2000) - txt.print_ub(uw > 1999) - txt.print_ub(uw >= 2000) - txt.spc() - txt.print_ub(f == -100.0) - txt.print_ub(f != -99.0) - txt.print_ub(f < -99.0) - txt.print_ub(f <= -100.0) - txt.print_ub(f > -101.0) - txt.print_ub(f >= -100.0) - txt.nl() - - txt.print("all 0: ") - txt.print_ub(b == -99) - txt.print_ub(b != -100) - txt.print_ub(b < -100) - txt.print_ub(b <= -101) - txt.print_ub(b > -100) - txt.print_ub(b >= -99) - txt.print_ub(ub ==21) - txt.print_ub(ub !=20) - txt.print_ub(ub <20) - txt.print_ub(ub <=19) - txt.print_ub(ub>20) - txt.print_ub(ub>=21) - txt.spc() - txt.print_ub(w == -20001) - txt.print_ub(w != -20000) - txt.print_ub(w < -20000) - txt.print_ub(w <= -20001) - txt.print_ub(w > -20000) - txt.print_ub(w >= -19999) - txt.print_ub(uw == 1999) - txt.print_ub(uw != 2000) - txt.print_ub(uw < 2000) - txt.print_ub(uw <= 1999) - txt.print_ub(uw > 2000) - txt.print_ub(uw >= 2001) - txt.spc() - txt.print_ub(f == -99.0) - txt.print_ub(f != -100.0) - txt.print_ub(f < -100.0) - txt.print_ub(f <= -101.0) - txt.print_ub(f > -100.0) - txt.print_ub(f >= -99.0) - txt.nl() - - ; TODO ALL OF THE ABOVE BUT WITH A VARIABLE INSTEAD OF A CONST VALUE - - - b = -100 - while b <= -20 - b++ - txt.print_b(b) - txt.print(" -19\n") - b = -100 - while b < -20 - b++ - txt.print_b(b) - txt.print(" -20\n") - - ub = 20 - while ub <= 200 - ub++ - txt.print_ub(ub) - txt.print(" 201\n") - ub = 20 - while ub < 200 - ub++ - txt.print_ub(ub) - txt.print(" 200\n") - - w = -20000 - while w <= -8000 { - w++ + if (string.compare(name, "aaa")==0) or (string.compare(name, "john")==0) or (string.compare(name, "bbb")==0) { + txt.print("name1 ok\n") } - txt.print_w(w) - txt.print(" -7999\n") - w = -20000 - while w < -8000 { - w++ + if (string.compare(name, "aaa")==0) or (string.compare(name, "zzz")==0) or (string.compare(name, "bbb")==0) { + txt.print("name2 fail!\n") } - txt.print_w(w) - txt.print(" -8000\n") - uw = 2000 - while uw <= 8000 { - uw++ - } - txt.print_uw(uw) - txt.print(" 8001\n") - uw = 2000 - while uw < 8000 { - uw++ - } - txt.print_uw(uw) - txt.print(" 8000\n") + if name=="aaa" or name=="john" or name=="bbb" ; TODO fix this result on C64 target, no newexpr! + txt.print("name1b ok\n") + if name=="aaa" or name=="zzz" or name=="bbb" ; TODO fix this result on C64 target, no newexpr! + txt.print("name2b fail!\n") - f = 0.0 - while f<2.2 { - f+=0.1 - } - floats.print_f(f) - txt.print(" 2.2\n") + +; txt.print("all 1: ") +; txt.print_ub(b == -100) +; txt.print_ub(b != -99) +; txt.print_ub(b < -99) +; txt.print_ub(b <= -100) +; txt.print_ub(b > -101) +; txt.print_ub(b >= -100) +; txt.print_ub(ub ==20) +; txt.print_ub(ub !=19) +; txt.print_ub(ub <21) +; txt.print_ub(ub <=20) +; txt.print_ub(ub>19) +; txt.print_ub(ub>=20) +; txt.spc() +; txt.print_ub(w == -20000) +; txt.print_ub(w != -19999) +; txt.print_ub(w < -19999) +; txt.print_ub(w <= -20000) +; txt.print_ub(w > -20001) +; txt.print_ub(w >= -20000) +; txt.print_ub(uw == 2000) +; txt.print_ub(uw != 2001) +; txt.print_ub(uw < 2001) +; txt.print_ub(uw <= 2000) +; txt.print_ub(uw > 1999) +; txt.print_ub(uw >= 2000) +; txt.spc() +; txt.print_ub(f == -100.0) +; txt.print_ub(f != -99.0) +; txt.print_ub(f < -99.0) +; txt.print_ub(f <= -100.0) +; txt.print_ub(f > -101.0) +; txt.print_ub(f >= -100.0) +; txt.nl() +; +; txt.print("all 0: ") +; txt.print_ub(b == -99) +; txt.print_ub(b != -100) +; txt.print_ub(b < -100) +; txt.print_ub(b <= -101) +; txt.print_ub(b > -100) +; txt.print_ub(b >= -99) +; txt.print_ub(ub ==21) +; txt.print_ub(ub !=20) +; txt.print_ub(ub <20) +; txt.print_ub(ub <=19) +; txt.print_ub(ub>20) +; txt.print_ub(ub>=21) +; txt.spc() +; txt.print_ub(w == -20001) +; txt.print_ub(w != -20000) +; txt.print_ub(w < -20000) +; txt.print_ub(w <= -20001) +; txt.print_ub(w > -20000) +; txt.print_ub(w >= -19999) +; txt.print_ub(uw == 1999) +; txt.print_ub(uw != 2000) +; txt.print_ub(uw < 2000) +; txt.print_ub(uw <= 1999) +; txt.print_ub(uw > 2000) +; txt.print_ub(uw >= 2001) +; txt.spc() +; txt.print_ub(f == -99.0) +; txt.print_ub(f != -100.0) +; txt.print_ub(f < -100.0) +; txt.print_ub(f <= -101.0) +; txt.print_ub(f > -100.0) +; txt.print_ub(f >= -99.0) +; txt.nl() +; +; ; TODO ALL OF THE ABOVE BUT WITH A VARIABLE INSTEAD OF A CONST VALUE +; +; +; b = -100 +; while b <= -20 +; b++ +; txt.print_b(b) +; txt.print(" -19\n") +; b = -100 +; while b < -20 +; b++ +; txt.print_b(b) +; txt.print(" -20\n") +; +; ub = 20 +; while ub <= 200 +; ub++ +; txt.print_ub(ub) +; txt.print(" 201\n") +; ub = 20 +; while ub < 200 +; ub++ +; txt.print_ub(ub) +; txt.print(" 200\n") +; +; w = -20000 +; while w <= -8000 { +; w++ +; } +; txt.print_w(w) +; txt.print(" -7999\n") +; w = -20000 +; while w < -8000 { +; w++ +; } +; txt.print_w(w) +; txt.print(" -8000\n") +; +; uw = 2000 +; while uw <= 8000 { +; uw++ +; } +; txt.print_uw(uw) +; txt.print(" 8001\n") +; uw = 2000 +; while uw < 8000 { +; uw++ +; } +; txt.print_uw(uw) +; txt.print(" 8000\n") +; +; f = 0.0 +; while f<2.2 { +; f+=0.1 +; } +; floats.print_f(f) +; txt.print(" 2.2\n") } } From 07fde7f6cc7cf9bc097fa06255b18e4e1ea2865b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 28 Mar 2023 19:50:03 +0200 Subject: [PATCH 4/6] fix IR same register error --- .../src/prog8/codegen/intermediate/BuiltinFuncGen.kt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 898ecc834..4aa5855ab 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -47,19 +47,15 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } private fun funcStringCompare(call: PtBuiltinFunctionCall): ExpressionCodeResult { -/* - loadm.w r65500,string.compare.st1 - loadm.w r65501,string.compare.st2 - syscall 29 - returnreg.b r0 - */ val result = mutableListOf() val left = exprGen.translateExpression(call.args[0]) val right = exprGen.translateExpression(call.args[1]) + val targetReg = codeGen.registers.nextFree() addToResult(result, left, 65500, -1) addToResult(result, right, 65501, -1) addInstr(result, IRInstruction(Opcode.SYSCALL, value=IMSyscall.COMPARE_STRINGS.number), null) - return ExpressionCodeResult(result, IRDataType.BYTE, 0, -1) + addInstr(result, IRInstruction(Opcode.LOADR, IRDataType.BYTE, reg1=targetReg, reg2=0), null) + return ExpressionCodeResult(result, IRDataType.BYTE, targetReg, -1) } private fun funcCmp(call: PtBuiltinFunctionCall): ExpressionCodeResult { From f4bf00ad31dd55c047114f9295ba8271432d9cd5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 28 Mar 2023 21:32:59 +0200 Subject: [PATCH 5/6] fix string compare and ifelse --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 8 +-- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 6 +- compiler/src/prog8/compiler/Compiler.kt | 55 +++++++++++++------ examples/test.p8 | 4 +- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 157293f6b..c003c5ac8 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -583,15 +583,15 @@ class AsmGen6502Internal ( else -> throw AssemblyError("weird jump") } when(stmt.condition.type) { - in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, label) - in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, label) + in WordDatatypes -> translateWordNotEqualsJump(stmt.condition, zero, leftConst, zero, label) + in ByteDatatypes -> translateByteNotEqualsJump(stmt.condition, zero, leftConst, zero, label) else -> throw AssemblyError("weird condition dt") } } else { val endLabel = makeLabel("if_end") when(stmt.condition.type) { - in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) - in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) + in WordDatatypes -> translateWordNotEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) + in ByteDatatypes -> translateByteNotEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) else -> throw AssemblyError("weird condition dt") } translate(stmt.ifScope) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index aba769dd2..78fa0b4b5 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -70,17 +70,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, "rrestorex" -> funcRrestoreX() "cmp" -> funcCmp(fcall) "callfar" -> funcCallFar(fcall) - "prog8_lib_stringcompare" -> funcStringCompare(fcall) + "prog8_lib_stringcompare" -> funcStringCompare(fcall, resultToStack) else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}") } return BuiltinFunctions.getValue(fcall.name).returnType } - private fun funcStringCompare(fcall: PtBuiltinFunctionCall) { + private fun funcStringCompare(fcall: PtBuiltinFunctionCall, resultToStack: Boolean) { assignAsmGen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_W2", DataType.UWORD) assignAsmGen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY, false) asmgen.out(" jsr prog8_lib.strcmp_mem") + if(resultToStack) + asmgen.out(" sta P8ESTACK_LO,x | dex") } private fun funcRsave() { diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index bb58ae311..c4f8de731 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -4,6 +4,7 @@ import com.github.michaelbull.result.onFailure import prog8.ast.IBuiltinFunctions import prog8.ast.Program import prog8.ast.base.AstException +import prog8.ast.base.FatalAstException import prog8.ast.expressions.Expression import prog8.ast.expressions.NumericLiteral import prog8.ast.statements.Directive @@ -428,9 +429,28 @@ private fun createAssemblyAndAssemble(program: PtProgram, private fun transformNewExpressions(program: PtProgram) { val newVariables = mutableMapOf>() + var countByteVars = 0 + var countWordVars = 0 + var countFloatVars = 0 + // TODO: find a reliable way to reuse the temp vars across expressions - fun getExprVar(what: String, type: DataType, count: Int, pos: Position, scope: PtSub): PtIdentifier { - val name = "p8p_exprvar_${what}_${count}_${type.toString().lowercase()}" + fun getExprVar(type: DataType, pos: Position, scope: PtSub): PtIdentifier { + val count = when(type) { + in ByteDatatypes -> { + countByteVars++ + countByteVars + } + in WordDatatypes -> { + countWordVars++ + countWordVars + } + DataType.FLOAT -> { + countFloatVars++ + countFloatVars + } + else -> throw FatalAstException("weird dt") + } + val name = "p8p_exprvar_${count}_${type.toString().lowercase()}" var subVars = newVariables[scope] if(subVars==null) { subVars = mutableListOf() @@ -442,21 +462,21 @@ private fun transformNewExpressions(program: PtProgram) { return PtIdentifier("${scope.scopedName}.$name", type, pos) } - fun transformExpr(expr: PtBinaryExpression, postfix: String, depth: Int): Pair> { + fun transformExpr(expr: PtBinaryExpression): Pair> { // depth first process the expression tree val scope = expr.definingSub()!! val assignments = mutableListOf() - fun transformOperand(node: PtExpression, kind: String): PtNode { + fun transformOperand(node: PtExpression): PtNode { return when(node) { is PtNumber, is PtIdentifier, is PtArray, is PtString, is PtMachineRegister -> node is PtBinaryExpression -> { - val (replacement, subAssigns) = transformExpr(node, kind, depth+1) + val (replacement, subAssigns) = transformExpr(node) assignments.addAll(subAssigns) replacement } else -> { - val variable = getExprVar(kind, node.type, depth, node.position, scope) + val variable = getExprVar(node.type, node.position, scope) val assign = PtAssignment(node.position) val target = PtAssignTarget(variable.position) target.add(variable) @@ -468,26 +488,26 @@ private fun transformNewExpressions(program: PtProgram) { } } - val newLeft = transformOperand(expr.left,"l") - val newRight = transformOperand(expr.right, "r") + val newLeft = transformOperand(expr.left) + val newRight = transformOperand(expr.right) // process the binexpr val resultVar = if(expr.type == expr.left.type) { - getExprVar(postfix, expr.type, depth, expr.position, scope) + getExprVar(expr.type, expr.position, scope) } else { if(expr.operator in ComparisonOperators && expr.type in ByteDatatypes) { // this is very common and should be dealth with correctly; byte==0, word>42 val varType = if(expr.left.type in PassByReferenceDatatypes) DataType.UWORD else expr.left.type - getExprVar(postfix, varType, depth, expr.position, scope) + getExprVar(varType, expr.position, scope) } else if(expr.left.type in PassByReferenceDatatypes && expr.type==DataType.UBYTE) { // this is common and should be dealth with correctly; for instance "name"=="john" val varType = if (expr.left.type in PassByReferenceDatatypes) DataType.UWORD else expr.left.type - getExprVar(postfix, varType, depth, expr.position, scope) + getExprVar(varType, expr.position, scope) } else if(expr.left.type equalsSize expr.type) { - getExprVar(postfix, expr.type, depth, expr.position, scope) + getExprVar(expr.type, expr.position, scope) } else { TODO("expression type differs from left operand type! got ${expr.left.type} expected ${expr.type} ${expr.position}") } @@ -539,12 +559,13 @@ private fun transformNewExpressions(program: PtProgram) { } } - fun transform(node: PtNode, parent: PtNode, depth: Int) { + fun transform(node: PtNode, parent: PtNode) { if(node is PtBinaryExpression) { + println("BINEXPR AT ${node.position}") node.children.toTypedArray().forEach { - transform(it, node, depth+1) + transform(it, node) } - val (rep, assignments) = transformExpr(node, "l", depth) + val (rep, assignments) = transformExpr(node) var replacement = rep if(!(rep.type equalsSize node.type)) { if(rep.type in NumericDatatypes && node.type in ByteDatatypes) { @@ -565,13 +586,13 @@ private fun transformNewExpressions(program: PtProgram) { stmt.parent.add(idx, it as PtNode) } } else { - node.children.toTypedArray().forEach { child -> transform(child, node, depth+1) } + node.children.toTypedArray().forEach { child -> transform(child, node) } } } program.allBlocks().forEach { block -> block.children.toTypedArray().forEach { - transform(it, block, 0) + transform(it, block) } } diff --git a/examples/test.p8 b/examples/test.p8 index ac1286195..89b2a836c 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -19,9 +19,9 @@ main { txt.print("name2 fail!\n") } - if name=="aaa" or name=="john" or name=="bbb" ; TODO fix this result on C64 target, no newexpr! + if name=="aaa" or name=="john" or name=="bbb" txt.print("name1b ok\n") - if name=="aaa" or name=="zzz" or name=="bbb" ; TODO fix this result on C64 target, no newexpr! + if name=="aaa" or name=="zzz" or name=="bbb" txt.print("name2b fail!\n") From 4598a83e8eb0b6b6aabc30321a2f3ecb96c3fd44 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 29 Mar 2023 02:23:02 +0200 Subject: [PATCH 6/6] fixing new comparisons --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 169 ++--- .../assignment/AugmentableAssignmentAsmGen.kt | 501 +++++++----- compiler/src/prog8/compiler/Compiler.kt | 3 +- .../compiler/astprocessing/CodeDesugarer.kt | 2 +- compiler/test/comparisons/test_compares.p8 | 493 +++++++++++- examples/test.p8 | 713 ++++++++++++++---- 6 files changed, 1484 insertions(+), 397 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index c003c5ac8..b3b8b341f 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -554,7 +554,7 @@ class AsmGen6502Internal ( translateCompareAndJumpIfTrue(condition, jump) } else { val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalse(condition, endLabel) + translateCompareOrJumpIfFalse(condition, endLabel) translate(stmt.ifScope) out(endLabel) } @@ -562,7 +562,7 @@ class AsmGen6502Internal ( // both true and else parts val elseLabel = makeLabel("if_else") val endLabel = makeLabel("if_end") - translateCompareAndJumpIfFalse(condition, elseLabel) + translateCompareOrJumpIfFalse(condition, elseLabel) translate(stmt.ifScope) jmp(endLabel) out(elseLabel) @@ -576,6 +576,7 @@ class AsmGen6502Internal ( if (stmt.elseScope.children.isEmpty()) { val jump = stmt.ifScope.children.singleOrNull() if (jump is PtJump) { + // jump somewhere if X!=0 val label = when { jump.generatedLabel!=null -> jump.generatedLabel!! jump.identifier!=null -> asmSymbolName(jump.identifier!!) @@ -583,15 +584,16 @@ class AsmGen6502Internal ( else -> throw AssemblyError("weird jump") } when(stmt.condition.type) { - in WordDatatypes -> translateWordNotEqualsJump(stmt.condition, zero, leftConst, zero, label) - in ByteDatatypes -> translateByteNotEqualsJump(stmt.condition, zero, leftConst, zero, label) + in WordDatatypes -> translateWordEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label) + in ByteDatatypes -> translateByteEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, label) else -> throw AssemblyError("weird condition dt") } } else { + // skip the true block (=jump to end label) if X==0 val endLabel = makeLabel("if_end") when(stmt.condition.type) { - in WordDatatypes -> translateWordNotEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) - in ByteDatatypes -> translateByteNotEqualsJump(stmt.condition, zero, leftConst, zero, endLabel) + in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel) + in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, endLabel) else -> throw AssemblyError("weird condition dt") } translate(stmt.ifScope) @@ -602,8 +604,8 @@ class AsmGen6502Internal ( val elseLabel = makeLabel("if_else") val endLabel = makeLabel("if_end") when(stmt.condition.type) { - in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, elseLabel) - in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, elseLabel) + in WordDatatypes -> translateWordNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel) + in ByteDatatypes -> translateByteNotEqualsOrJumpElsewhere(stmt.condition, zero, leftConst, zero, elseLabel) else -> throw AssemblyError("weird condition dt") } translate(stmt.ifScope) @@ -1172,15 +1174,16 @@ $repeatLabel lda $counterVar jump.address!=null -> jump.address!!.toHex() else -> throw AssemblyError("weird jump") } - if (rightConstVal!=null && rightConstVal.number == 0.0) - testZeroAndJump(left, invertedComparisonOperator, label) + if (rightConstVal!=null && rightConstVal.number == 0.0) { + testZeroOrJumpElsewhere(left, invertedComparisonOperator, label) + } else { val leftConstVal = left as? PtNumber - testNonzeroComparisonAndJump(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal) + testNonzeroComparisonOrJumpElsewhere(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal) } } - private fun translateCompareAndJumpIfFalse(expr: PtBinaryExpression, jumpIfFalseLabel: String) { + private fun translateCompareOrJumpIfFalse(expr: PtBinaryExpression, jumpIfFalseLabel: String) { val left = expr.left val right = expr.right val operator = expr.operator @@ -1188,19 +1191,19 @@ $repeatLabel lda $counterVar val rightConstVal = right as? PtNumber if (rightConstVal!=null && rightConstVal.number == 0.0) - testZeroAndJump(left, operator, jumpIfFalseLabel) + testZeroOrJumpElsewhere(left, operator, jumpIfFalseLabel) else - testNonzeroComparisonAndJump(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal) + testNonzeroComparisonOrJumpElsewhere(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal) } - private fun testZeroAndJump( + private fun testZeroOrJumpElsewhere( left: PtExpression, operator: String, jumpIfFalseLabel: String ) { val dt = left.type if(dt in IntegerDatatypes && left is PtIdentifier) - return testVariableZeroAndJump(left, dt, operator, jumpIfFalseLabel) + return testVariableZeroOrJumpElsewhere(left, dt, operator, jumpIfFalseLabel) when(dt) { DataType.BOOL, DataType.UBYTE, DataType.UWORD -> { @@ -1286,7 +1289,7 @@ $repeatLabel lda $counterVar } } - private fun testVariableZeroAndJump(variable: PtIdentifier, dt: DataType, operator: String, jumpIfFalseLabel: String) { + private fun testVariableZeroOrJumpElsewhere(variable: PtIdentifier, dt: DataType, operator: String, jumpIfFalseLabel: String) { // optimized code if the expression is just an identifier (variable) val varname = asmVariableName(variable) when(dt) { @@ -1346,7 +1349,7 @@ $repeatLabel lda $counterVar } } - internal fun testNonzeroComparisonAndJump( + internal fun testNonzeroComparisonOrJumpElsewhere( left: PtExpression, operator: String, right: PtExpression, @@ -1359,70 +1362,70 @@ $repeatLabel lda $counterVar when (operator) { "==" -> { when (dt) { - in ByteDatatypes -> translateByteEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - in WordDatatypes -> translateWordEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.FLOAT -> translateFloatEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.STR -> translateStringEqualsJump(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) + in ByteDatatypes -> 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) else -> throw AssemblyError("weird operand datatype") } } "!=" -> { when (dt) { - in ByteDatatypes -> translateByteNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - in WordDatatypes -> translateWordNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.FLOAT -> translateFloatNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.STR -> translateStringNotEqualsJump(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) + in ByteDatatypes -> 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) else -> throw AssemblyError("weird operand datatype") } } "<" -> { when(dt) { - DataType.UBYTE -> translateUbyteLessJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.BYTE -> translateByteLessJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.UWORD -> translateUwordLessJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.WORD -> translateWordLessJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.FLOAT -> translateFloatLessJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.STR -> translateStringLessJump(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) + DataType.UBYTE -> translateUbyteLessOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteLessOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordLessOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordLessOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> translateFloatLessOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.STR -> translateStringLessOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) else -> throw AssemblyError("weird operand datatype") } } "<=" -> { when(dt) { - DataType.UBYTE -> translateUbyteLessOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.BYTE -> translateByteLessOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.UWORD -> translateUwordLessOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.WORD -> translateWordLessOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.FLOAT -> translateFloatLessOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.STR -> translateStringLessOrEqualJump(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) + DataType.UBYTE -> translateUbyteLessOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteLessOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordLessOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordLessOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> translateFloatLessOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.STR -> translateStringLessOrEqualOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) else -> throw AssemblyError("weird operand datatype") } } ">" -> { when(dt) { - DataType.UBYTE -> translateUbyteGreaterJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.BYTE -> translateByteGreaterJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.UWORD -> translateUwordGreaterJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.WORD -> translateWordGreaterJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.FLOAT -> translateFloatGreaterJump(left, right, leftConstVal,rightConstVal, jumpIfFalseLabel) - DataType.STR -> translateStringGreaterJump(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) + DataType.UBYTE -> translateUbyteGreaterOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteGreaterOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordGreaterOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordGreaterOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> translateFloatGreaterOrJumpElsewhere(left, right, leftConstVal,rightConstVal, jumpIfFalseLabel) + DataType.STR -> translateStringGreaterOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) else -> throw AssemblyError("weird operand datatype") } } ">=" -> { when(dt) { - DataType.UBYTE -> translateUbyteGreaterOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.BYTE -> translateByteGreaterOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.UWORD -> translateUwordGreaterOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.WORD -> translateWordGreaterOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.FLOAT -> translateFloatGreaterOrEqualJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) - DataType.STR -> translateStringGreaterOrEqualJump(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) + DataType.UBYTE -> translateUbyteGreaterOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.BYTE -> translateByteGreaterOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.UWORD -> translateUwordGreaterOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.WORD -> translateWordGreaterOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.FLOAT -> translateFloatGreaterOrEqualOrJumpElsewhere(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel) + DataType.STR -> translateStringGreaterOrEqualOrJumpElsewhere(left as PtIdentifier, right as PtIdentifier, jumpIfFalseLabel) else -> throw AssemblyError("weird operand datatype") } } } } - private fun translateFloatLessJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateFloatLessOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(leftConstVal!=null && rightConstVal!=null) { throw AssemblyError("const-compare should have been optimized away") } @@ -1467,7 +1470,7 @@ $repeatLabel lda $counterVar } } - private fun translateFloatLessOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateFloatLessOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(leftConstVal!=null && rightConstVal!=null) { throw AssemblyError("const-compare should have been optimized away") } @@ -1512,7 +1515,7 @@ $repeatLabel lda $counterVar } } - private fun translateFloatGreaterJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateFloatGreaterOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(leftConstVal!=null && rightConstVal!=null) { throw AssemblyError("const-compare should have been optimized away") } @@ -1557,7 +1560,7 @@ $repeatLabel lda $counterVar } } - private fun translateFloatGreaterOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateFloatGreaterOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(leftConstVal!=null && rightConstVal!=null) { throw AssemblyError("const-compare should have been optimized away") } @@ -1602,7 +1605,7 @@ $repeatLabel lda $counterVar } } - private fun translateUbyteLessJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUbyteLessOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(cmpOperand: String) { out(" cmp $cmpOperand | bcs $jumpIfFalseLabel") @@ -1647,7 +1650,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateByteLessJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateByteLessOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(sbcOperand: String) { out(""" @@ -1688,7 +1691,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateUwordLessJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUwordLessOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCpyOperand: String, lsbCmpOperand: String) { out(""" @@ -1732,7 +1735,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_less_uw | beq $jumpIfFalseLabel") } - private fun translateWordLessJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateWordLessOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCpyOperand: String, lsbCmpOperand: String) { out(""" @@ -1778,7 +1781,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_less_w | beq $jumpIfFalseLabel") } - private fun translateUbyteGreaterJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUbyteGreaterOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(cmpOperand: String) { out(""" @@ -1824,7 +1827,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateByteGreaterJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateByteGreaterOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(sbcOperand: String) { out(""" @@ -1867,7 +1870,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateUwordGreaterJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUwordGreaterOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCpyOperand: String, lsbCmpOperand: String) { out(""" @@ -1917,7 +1920,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_W2+1", "P8ZP_SCRATCH_W2") } - private fun translateWordGreaterJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateWordGreaterOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCmpOperand: String, lsbCmpOperand: String) { out(""" @@ -1968,7 +1971,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_less_w | beq $jumpIfFalseLabel") } - private fun translateUbyteLessOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUbyteLessOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(cmpOperand: String) { out(""" @@ -2015,7 +2018,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateByteLessOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateByteLessOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(sbcOperand: String) { out(""" clc @@ -2058,7 +2061,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateUwordLessOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUwordLessOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCpyOperand: String, lsbCmpOperand: String) { out(""" @@ -2110,7 +2113,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_lesseq_uw | beq $jumpIfFalseLabel") } - private fun translateWordLessOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateWordLessOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(leftName: String) { out(""" @@ -2165,7 +2168,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_lesseq_w | beq $jumpIfFalseLabel") } - private fun translateUbyteGreaterOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUbyteGreaterOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(cmpOperand: String) { out(" cmp $cmpOperand | bcc $jumpIfFalseLabel") @@ -2208,7 +2211,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateByteGreaterOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateByteGreaterOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(sbcOperand: String) { out(""" sec @@ -2248,7 +2251,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateUwordGreaterOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateUwordGreaterOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCpyOperand: String, lsbCmpOperand: String) { out(""" @@ -2291,7 +2294,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_lesseq_uw | beq $jumpIfFalseLabel") } - private fun translateWordGreaterOrEqualJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateWordGreaterOrEqualOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(msbCpyOperand: String, lsbCmpOperand: String) { out(""" @@ -2337,7 +2340,7 @@ $repeatLabel lda $counterVar return out(" jsr prog8_lib.reg_lesseq_w | beq $jumpIfFalseLabel") } - private fun translateByteEqualsJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateByteEqualsOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(cmpOperand: String) { out(" cmp $cmpOperand | bne $jumpIfFalseLabel") } @@ -2382,7 +2385,7 @@ $repeatLabel lda $counterVar out(" cmp P8ZP_SCRATCH_B1 | bne $jumpIfFalseLabel") } - private fun translateByteNotEqualsJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateByteNotEqualsOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { fun code(cmpOperand: String) { out(" cmp $cmpOperand | beq $jumpIfFalseLabel") @@ -2428,7 +2431,7 @@ $repeatLabel lda $counterVar return code("P8ZP_SCRATCH_B1") } - private fun translateWordEqualsJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateWordEqualsOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(rightConstVal!=null) { if(leftConstVal!=null) { if(rightConstVal!=leftConstVal) @@ -2512,7 +2515,7 @@ $repeatLabel lda $counterVar } - private fun translateWordNotEqualsJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateWordNotEqualsOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(rightConstVal!=null) { if(leftConstVal!=null) { @@ -2600,7 +2603,7 @@ $repeatLabel lda $counterVar } - private fun translateFloatEqualsJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateFloatEqualsOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(rightConstVal!=null) { if(leftConstVal!=null) { if(rightConstVal!=leftConstVal) @@ -2684,7 +2687,7 @@ $repeatLabel lda $counterVar } } - private fun translateFloatNotEqualsJump(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { + private fun translateFloatNotEqualsOrJumpElsewhere(left: PtExpression, right: PtExpression, leftConstVal: PtNumber?, rightConstVal: PtNumber?, jumpIfFalseLabel: String) { if(rightConstVal!=null) { if(leftConstVal!=null) { if(rightConstVal==leftConstVal) @@ -2769,7 +2772,7 @@ $repeatLabel lda $counterVar } } - private fun translateStringEqualsJump(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { + private fun translateStringEqualsOrJumpElsewhere(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { val leftNam = asmVariableName(left) val rightNam = asmVariableName(right) out(""" @@ -2780,11 +2783,10 @@ $repeatLabel lda $counterVar lda #<$leftNam ldy #>$leftNam jsr prog8_lib.strcmp_mem - cmp #0 bne $jumpIfFalseLabel""") } - private fun translateStringNotEqualsJump(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { + private fun translateStringNotEqualsOrJumpElsewhere(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { val leftNam = asmVariableName(left) val rightNam = asmVariableName(right) out(""" @@ -2795,11 +2797,10 @@ $repeatLabel lda $counterVar lda #<$leftNam ldy #>$leftNam jsr prog8_lib.strcmp_mem - cmp #0 beq $jumpIfFalseLabel""") } - private fun translateStringLessJump(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { + private fun translateStringLessOrJumpElsewhere(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { val leftNam = asmVariableName(left) val rightNam = asmVariableName(right) out(""" @@ -2813,7 +2814,7 @@ $repeatLabel lda $counterVar bpl $jumpIfFalseLabel""") } - private fun translateStringGreaterJump(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { + private fun translateStringGreaterOrJumpElsewhere(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { val leftNam = asmVariableName(left) val rightNam = asmVariableName(right) out(""" @@ -2828,7 +2829,7 @@ $repeatLabel lda $counterVar bmi $jumpIfFalseLabel""") } - private fun translateStringLessOrEqualJump(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { + private fun translateStringLessOrEqualOrJumpElsewhere(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { val leftNam = asmVariableName(left) val rightNam = asmVariableName(right) out(""" @@ -2844,7 +2845,7 @@ $repeatLabel lda $counterVar +""") } - private fun translateStringGreaterOrEqualJump(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { + private fun translateStringGreaterOrEqualOrJumpElsewhere(left: PtIdentifier, right: PtIdentifier, jumpIfFalseLabel: String) { val leftNam = asmVariableName(left) val rightNam = asmVariableName(right) out(""" diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index 2cd2c7f0d..e7284e706 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -668,43 +668,31 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, } "<" -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.A) - asmgen.out(""" - cmp $name - bcc + - beq + - lda #1 - bne ++ -+ lda #0 -+ sta $name""") + if(dt==DataType.UBYTE) + TODO("ubyte <") + else + TODO("byte <") } "<=" -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.A) - asmgen.out(""" - cmp $name - lda #0 - adc #0 - sta $name""") + if(dt==DataType.UBYTE) + TODO("ubyte <=") + else + TODO("byte <=") } ">" -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.A) - asmgen.out(""" - cmp $name - bcc + - lda #0 - beq ++ -+ lda #1 -+ sta $name""") + if(dt==DataType.UBYTE) + TODO("ubyte >") + else + TODO("byte >") } ">=" -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.A) - asmgen.out(""" - cmp $name - bcc + - beq + - lda #0 - beq ++ -+ lda #1 -+ sta $name""") + if(dt==DataType.UBYTE) + TODO("ubyte >=") + else + TODO("byte >=") } else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -782,41 +770,106 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, + sta $name""") } "<" -> { - asmgen.out(""" - lda $name - cmp $otherName - bcs + - lda #1 - bne ++ -+ lda #0 -+ sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $name + cmp $otherName + bcc + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } + else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + sec + sbc $otherName + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } "<=" -> { - asmgen.out(""" - lda $otherName - cmp $name - lda #0 - adc #0 - sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $otherName + cmp $name + bcs + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + clc + sbc $otherName + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } ">" -> { - asmgen.out(""" - lda $otherName - cmp $name - bcc + - lda #0 - beq ++ -+ lda #1 -+ sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $name + cmp $otherName + beq + + bcs ++ ++ lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + clc + sbc $otherName + bvc + + eor #$80 ++ bpl + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } ">=" -> { - asmgen.out(""" - lda $name - cmp $otherName - lda #0 - adc #0 - sta $name""") - } + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $name + cmp $otherName + bcs + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + sec + sbc $otherName + bvc + + eor #$80 ++ bpl + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } else -> throw AssemblyError("invalid operator for in-place modification $operator") } } @@ -908,40 +961,106 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, + sta $name""") } "<" -> { - asmgen.out(""" - lda $name - cmp #$value - bcs + - lda #1 - bne ++ -+ lda #0 -+ sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $name + cmp #$value + bcc + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } + else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + sec + sbc #$value + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } "<=" -> { - asmgen.out(""" - lda #$value - cmp $name - lda #0 - adc #0 - sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda #$value + cmp $name + bcs + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + clc + sbc #$value + bvc + + eor #$80 ++ bmi + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } ">" -> { - asmgen.out(""" - lda #$value - cmp $name - bcc + - lda #0 - beq ++ -+ lda #1 -+ sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $name + cmp #$value + beq + + bcs ++ ++ lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + clc + sbc #$value + bvc + + eor #$80 ++ bpl + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } ">=" -> { - asmgen.out(""" - lda $name - cmp #$value - lda #0 - adc #0 - sta $name""") + if(dt==DataType.UBYTE) { + asmgen.out(""" + lda $name + cmp #$value + bcs + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } else { + // see http://www.6502.org/tutorials/compare_beyond.html + asmgen.out(""" + lda $name + sec + sbc #$value + bvc + + eor #$80 ++ bpl + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } } else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -1816,33 +1935,63 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, sta $name+1""") } "<=" -> { - val compareRoutine = if(dt==DataType.UWORD) "reg_lesseq_uw" else "reg_lesseq_w" - asmgen.out(""" + if(dt==DataType.UWORD) { + asmgen.out(""" lda $otherName ldy $otherName+1 sta P8ZP_SCRATCH_W2 sty P8ZP_SCRATCH_W2+1 lda $name ldy $name+1 - jsr prog8_lib.$compareRoutine + jsr prog8_lib.reg_lesseq_uw sta $name lda #0 sta $name+1""") + } else { + // note: reg_lesseq_w routine takes the arguments in reverse order + asmgen.out(""" + lda $name + ldy $name+1 + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + lda $otherName + ldy $otherName+1 + jsr prog8_lib.reg_lesseq_w + sta $name + lda #0 + sta $name+1""") + } } ">=" -> { // a>=b --> b<=a - val compareRoutine = if(dt==DataType.UWORD) "reg_lesseq_uw" else "reg_lesseq_w" - asmgen.out(""" + if(dt==DataType.UWORD) { + asmgen.out(""" lda $name ldy $name+1 sta P8ZP_SCRATCH_W2 sty P8ZP_SCRATCH_W2+1 lda $otherName ldy $otherName+1 - jsr prog8_lib.$compareRoutine + jsr prog8_lib.reg_lesseq_uw sta $name lda #0 - sta $name+1""") + sta $name+1""" + ) + } else { + // note: reg_lesseq_w routine takes the arguments in reverse order + asmgen.out(""" + lda $otherName + ldy $otherName+1 + sta P8ZP_SCRATCH_W2 + sty P8ZP_SCRATCH_W2+1 + lda $name + ldy $name+1 + jsr prog8_lib.reg_lesseq_w + sta $name + lda #0 + sta $name+1""" + ) + } } else -> throw AssemblyError("invalid operator for in-place modification $operator") } @@ -2177,9 +2326,12 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, """) } // pretty uncommon, who's going to assign a comparison boolean expresion to a float var: - "==", "!=", "<", "<=", ">", ">=" -> TODO("float-value-to-var comparisons") + "==" -> TODO("float-value-to-var comparison ==") + "!=" -> TODO("float-value-to-var comparison !=") + "<", "<=", ">", ">=" -> TODO("float-value-to-var comparisons") else -> throw AssemblyError("invalid operator for in-place float modification $operator") } + // store Fac1 back into memory asmgen.out(""" ldx #<$name ldy #>$name @@ -2232,7 +2384,67 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, """) } // pretty uncommon, who's going to assign a comparison boolean expresion to a float var: - "==", "!=", "<", "<=", ">", ">=" -> TODO("float-var-to-var comparisons") + "==" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$otherName + ldy #>$otherName + jsr floats.var_fac1_notequal_f + eor #1 + jsr floats.FREADSA""") + } + "!=" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$otherName + ldy #>$otherName + jsr floats.var_fac1_notequal_f + jsr floats.FREADSA""") + } + "<" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$otherName + ldy #>$otherName + jsr floats.var_fac1_less_f + jsr floats.FREADSA""") + } + "<=" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$otherName + ldy #>$otherName + jsr floats.var_fac1_lesseq_f + jsr floats.FREADSA""") + } + ">" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$otherName + ldy #>$otherName + jsr floats.var_fac1_greater_f + jsr floats.FREADSA""") + } + ">=" -> { + asmgen.out(""" + lda #<$name + ldy #>$name + jsr floats.MOVFM + lda #<$otherName + ldy #>$otherName + jsr floats.var_fac1_greatereq_f + jsr floats.FREADSA""") + } else -> throw AssemblyError("invalid operator for in-place float modification $operator") } // store Fac1 back into memory @@ -2299,41 +2511,22 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, asmgen.out(""" lda #<$name ldy #>$name - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 + jsr floats.MOVFM lda #<$constValueName ldy #>$constValueName - jsr floats.vars_equal_f - bne +""") - val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) - assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) - asmgen.out(""" - jmp ++ -+""") - assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) - asmgen.out("+") - asmgen.restoreRegisterLocal(CpuRegister.X) - return + jsr floats.var_fac1_notequal_f + eor #1 + jsr floats.FREADSA""") } "!=" -> { asmgen.out(""" lda #<$name ldy #>$name - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 + jsr floats.MOVFM lda #<$constValueName ldy #>$constValueName - jsr floats.vars_equal_f - beq +""") - val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) - assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) - asmgen.out(""" - jmp ++ -+""") - assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) - asmgen.out("+") - asmgen.restoreRegisterLocal(CpuRegister.X) - return + jsr floats.var_fac1_notequal_f + jsr floats.FREADSA""") } "<" -> { asmgen.out(""" @@ -2342,58 +2535,28 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, jsr floats.MOVFM lda #<$constValueName ldy #>$constValueName - jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than - cmp #0 - bmi +""") - val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) - assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) - asmgen.out(""" - jmp ++ -+""") - assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) - asmgen.out("+") - asmgen.restoreRegisterLocal(CpuRegister.X) - return + jsr floats.var_fac1_less_f + jsr floats.FREADSA""") } "<=" -> { asmgen.out(""" - lda #<$constValueName - ldy #>$constValueName - jsr floats.MOVFM lda #<$name ldy #>$name - jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than - cmp #0 - bpl +""") - val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) - assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) - asmgen.out(""" - jmp ++ -+""") - assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) - asmgen.out("+") - asmgen.restoreRegisterLocal(CpuRegister.X) - return + jsr floats.MOVFM + lda #<$constValueName + ldy #>$constValueName + jsr floats.var_fac1_lesseq_f + jsr floats.FREADSA""") } ">" -> { asmgen.out(""" - lda #<$constValueName - ldy #>$constValueName - jsr floats.MOVFM lda #<$name ldy #>$name - jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than - cmp #0 - bmi +""") - val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) - assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) - asmgen.out(""" - jmp ++ -+""") - assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) - asmgen.out("+") - asmgen.restoreRegisterLocal(CpuRegister.X) - return + jsr floats.MOVFM + lda #<$constValueName + ldy #>$constValueName + jsr floats.var_fac1_greater_f + jsr floats.FREADSA""") } ">=" -> { asmgen.out(""" @@ -2402,18 +2565,8 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, jsr floats.MOVFM lda #<$constValueName ldy #>$constValueName - jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than - cmp #0 - bpl +""") - val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name) - assignmentAsmGen.assignConstantFloat(nameTarget, 0.0) - asmgen.out(""" - jmp ++ -+""") - assignmentAsmGen.assignConstantFloat(nameTarget, 1.0) - asmgen.out("+") - asmgen.restoreRegisterLocal(CpuRegister.X) - return + jsr floats.var_fac1_greatereq_f + jsr floats.FREADSA""") } else -> throw AssemblyError("invalid operator for in-place float modification $operator") } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index c4f8de731..da67db0c2 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -413,7 +413,7 @@ private fun createAssemblyAndAssemble(program: PtProgram, if(compilerOptions.useNewExprCode) transformNewExpressions(program) - printAst(program, true) { println(it) } + // printAst(program, true) { println(it) } val stMaker = SymbolTableMaker(program, compilerOptions) val symbolTable = stMaker.make() @@ -561,7 +561,6 @@ private fun transformNewExpressions(program: PtProgram) { fun transform(node: PtNode, parent: PtNode) { if(node is PtBinaryExpression) { - println("BINEXPR AT ${node.position}") node.children.toTypedArray().forEach { transform(it, node) } diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 5ed3c5578..7fa098bc1 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -79,7 +79,7 @@ if CONDITION==0 while CONDITION { STUFF } ==> _whileloop: - if CONDITION==0 goto _after + if INVERTED-CONDITION goto _after STUFF goto _whileloop _after: diff --git a/compiler/test/comparisons/test_compares.p8 b/compiler/test/comparisons/test_compares.p8 index e2ad47107..0e293eb17 100644 --- a/compiler/test/comparisons/test_compares.p8 +++ b/compiler/test/comparisons/test_compares.p8 @@ -1,12 +1,40 @@ %zeropage basicsafe %import textio +%import floats +%import string main { sub start() { + test_string() + txt.nl() + test_compare_variable() + txt.nl() + test_compare_literal() + } + + sub test_string() { + str name="john" + + if (string.compare(name, "aaa")==0) or (string.compare(name, "john")==0) or (string.compare(name, "bbb")==0) { + txt.print("name1 ok\n") + } + if (string.compare(name, "aaa")==0) or (string.compare(name, "zzz")==0) or (string.compare(name, "bbb")==0) { + txt.print("name2 fail!\n") + } + + if name=="aaa" or name=="john" or name=="bbb" + txt.print("name1b ok\n") + if name=="aaa" or name=="zzz" or name=="bbb" + txt.print("name2b fail!\n") + + } + + sub test_compare_literal() { byte b = -100 ubyte ub = 20 word w = -20000 uword uw = 2000 + float f = -100 txt.print("all 1: ") txt.print_ub(b == -100) @@ -34,7 +62,15 @@ main { txt.print_ub(uw <= 2000) txt.print_ub(uw > 1999) txt.print_ub(uw >= 2000) + txt.spc() + txt.print_ub(f == -100.0) + txt.print_ub(f != -99.0) + txt.print_ub(f < -99.0) + txt.print_ub(f <= -100.0) + txt.print_ub(f > -101.0) + txt.print_ub(f >= -100.0) txt.nl() + txt.print("all 0: ") txt.print_ub(b == -99) txt.print_ub(b != -100) @@ -61,6 +97,153 @@ main { txt.print_ub(uw <= 1999) txt.print_ub(uw > 2000) txt.print_ub(uw >= 2001) + txt.spc() + txt.print_ub(f == -99.0) + txt.print_ub(f != -100.0) + txt.print_ub(f < -100.0) + txt.print_ub(f <= -101.0) + txt.print_ub(f > -100.0) + txt.print_ub(f >= -99.0) + txt.nl() + + txt.print("all .: ") + if b == -100 txt.chrout('.') + if b != -99 txt.chrout('.') + if b < -99 txt.chrout('.') + if b <= -100 txt.chrout('.') + if b > -101 txt.chrout('.') + if b >= -100 txt.chrout('.') + if ub ==20 txt.chrout('.') + if ub !=19 txt.chrout('.') + if ub <21 txt.chrout('.') + if ub <=20 txt.chrout('.') + if ub>19 txt.chrout('.') + if ub>=20 txt.chrout('.') + txt.spc() + if w == -20000 txt.chrout('.') + if w != -19999 txt.chrout('.') + if w < -19999 txt.chrout('.') + if w <= -20000 txt.chrout('.') + if w > -20001 txt.chrout('.') + if w >= -20000 txt.chrout('.') + if uw == 2000 txt.chrout('.') + if uw != 2001 txt.chrout('.') + if uw < 2001 txt.chrout('.') + if uw <= 2000 txt.chrout('.') + if uw > 1999 txt.chrout('.') + if uw >= 2000 txt.chrout('.') + txt.spc() + if f == -100.0 txt.chrout('.') + if f != -99.0 txt.chrout('.') + if f < -99.0 txt.chrout('.') + if f <= -100.0 txt.chrout('.') + if f > -101.0 txt.chrout('.') + if f >= -100.0 txt.chrout('.') + txt.nl() + + txt.print(" no !: ") + if b == -99 txt.chrout('!') + if b != -100 txt.chrout('!') + if b < -100 txt.chrout('!') + if b <= -101 txt.chrout('!') + if b > -100 txt.chrout('!') + if b >= -99 txt.chrout('!') + if ub ==21 txt.chrout('!') + if ub !=20 txt.chrout('!') + if ub <20 txt.chrout('!') + if ub <=19 txt.chrout('!') + if ub>20 txt.chrout('!') + if ub>=21 txt.chrout('!') + txt.spc() + if w == -20001 txt.chrout('!') + if w != -20000 txt.chrout('!') + if w < -20000 txt.chrout('!') + if w <= -20001 txt.chrout('!') + if w > -20000 txt.chrout('!') + if w >= -19999 txt.chrout('!') + if uw == 1999 txt.chrout('!') + if uw != 2000 txt.chrout('!') + if uw < 2000 txt.chrout('!') + if uw <= 1999 txt.chrout('!') + if uw > 2000 txt.chrout('!') + if uw >= 2001 txt.chrout('!') + txt.spc() + if f == -99.0 txt.chrout('!') + if f != -100.0 txt.chrout('!') + if f < -100.0 txt.chrout('!') + if f <= -101.0 txt.chrout('!') + if f > -100.0 txt.chrout('!') + if f >= -99.0 txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == -100 txt.chrout('.') else txt.chrout('!') + if b != -99 txt.chrout('.') else txt.chrout('!') + if b < -99 txt.chrout('.') else txt.chrout('!') + if b <= -100 txt.chrout('.') else txt.chrout('!') + if b > -101 txt.chrout('.') else txt.chrout('!') + if b >= -100 txt.chrout('.') else txt.chrout('!') + if ub ==20 txt.chrout('.') else txt.chrout('!') + if ub !=19 txt.chrout('.') else txt.chrout('!') + if ub <21 txt.chrout('.') else txt.chrout('!') + if ub <=20 txt.chrout('.') else txt.chrout('!') + if ub>19 txt.chrout('.') else txt.chrout('!') + if ub>=20 txt.chrout('.') else txt.chrout('!') + txt.spc() + if w == -20000 txt.chrout('.') else txt.chrout('!') + if w != -19999 txt.chrout('.') else txt.chrout('!') + if w < -19999 txt.chrout('.') else txt.chrout('!') + if w <= -20000 txt.chrout('.') else txt.chrout('!') + if w > -20001 txt.chrout('.') else txt.chrout('!') + if w >= -20000 txt.chrout('.') else txt.chrout('!') + if uw == 2000 txt.chrout('.') else txt.chrout('!') + if uw != 2001 txt.chrout('.') else txt.chrout('!') + if uw < 2001 txt.chrout('.') else txt.chrout('!') + if uw <= 2000 txt.chrout('.') else txt.chrout('!') + if uw > 1999 txt.chrout('.') else txt.chrout('!') + if uw >= 2000 txt.chrout('.') else txt.chrout('!') + txt.spc() + if f == -100.0 txt.chrout('.') else txt.chrout('!') + if f != -99.0 txt.chrout('.') else txt.chrout('!') + if f < -99.0 txt.chrout('.') else txt.chrout('!') + if f <= -100.0 txt.chrout('.') else txt.chrout('!') + if f > -101.0 txt.chrout('.') else txt.chrout('!') + if f >= -100.0 txt.chrout('.') else txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == -99 txt.chrout('!') else txt.chrout('.') + if b != -100 txt.chrout('!') else txt.chrout('.') + if b < -100 txt.chrout('!') else txt.chrout('.') + if b <= -101 txt.chrout('!') else txt.chrout('.') + if b > -100 txt.chrout('!') else txt.chrout('.') + if b >= -99 txt.chrout('!') else txt.chrout('.') + if ub ==21 txt.chrout('!') else txt.chrout('.') + if ub !=20 txt.chrout('!') else txt.chrout('.') + if ub <20 txt.chrout('!') else txt.chrout('.') + if ub <=19 txt.chrout('!') else txt.chrout('.') + if ub>20 txt.chrout('!') else txt.chrout('.') + if ub>=21 txt.chrout('!') else txt.chrout('.') + txt.spc() + if w == -20001 txt.chrout('!') else txt.chrout('.') + if w != -20000 txt.chrout('!') else txt.chrout('.') + if w < -20000 txt.chrout('!') else txt.chrout('.') + if w <= -20001 txt.chrout('!') else txt.chrout('.') + if w > -20000 txt.chrout('!') else txt.chrout('.') + if w >= -19999 txt.chrout('!') else txt.chrout('.') + if uw == 1999 txt.chrout('!') else txt.chrout('.') + if uw != 2000 txt.chrout('!') else txt.chrout('.') + if uw < 2000 txt.chrout('!') else txt.chrout('.') + if uw <= 1999 txt.chrout('!') else txt.chrout('.') + if uw > 2000 txt.chrout('!') else txt.chrout('.') + if uw >= 2001 txt.chrout('!') else txt.chrout('.') + txt.spc() + if f == -99.0 txt.chrout('!') else txt.chrout('.') + if f != -100.0 txt.chrout('!') else txt.chrout('.') + if f < -100.0 txt.chrout('!') else txt.chrout('.') + if f <= -101.0 txt.chrout('!') else txt.chrout('.') + if f > -100.0 txt.chrout('!') else txt.chrout('.') + if f >= -99.0 txt.chrout('!') else txt.chrout('.') txt.nl() @@ -112,9 +295,311 @@ main { txt.print_uw(uw) txt.print(" 8000\n") -; float f -; while f<2.2 { -; f+=0.1 -; } + f = 0.0 + floats.print_f(f) + while f<2.2 { + f+=0.1 + floats.print_f(f) + } + floats.print_f(f) + txt.print(" 2.2\n") + } + + sub test_compare_variable() { + byte b = -100 + ubyte ub = 20 + word w = -20000 + uword uw = 2000 + float f = -100 + + byte minus_100 = -100 + byte minus_99 = -99 + byte minus_20 = -20 + byte minus_101 = -101 + ubyte nineteen = 19 + ubyte twenty = 20 + ubyte twenty1 = 21 + ubyte twohundred = 200 + float f_minus_100 = -100.0 + float f_minus_101 = -101.0 + float f_minus_99 = -99.0 + float twodottwo = 2.2 + word minus8000 = -8000 + word eightthousand = 8000 + word w_min_20000 = -20000 + word w_min_19999 = -19999 + word w_min_20001 = -20001 + uword twothousand = 2000 + uword twothousand1 = 2001 + uword nineteen99 = 1999 + + + txt.print("all 1: ") + txt.print_ub(b == minus_100) + txt.print_ub(b != minus_99) + txt.print_ub(b < minus_99) + txt.print_ub(b <= minus_100) + txt.print_ub(b > minus_101) + txt.print_ub(b >= minus_100) + txt.print_ub(ub ==twenty) + txt.print_ub(ub !=nineteen) + txt.print_ub(ub nineteen) + txt.print_ub(ub>=twenty) + txt.spc() + txt.print_ub(w == w_min_20000) + txt.print_ub(w != w_min_19999) + txt.print_ub(w < w_min_19999) + txt.print_ub(w <= w_min_20000) + txt.print_ub(w > w_min_20001) + txt.print_ub(w >= w_min_20000) + txt.print_ub(uw == twothousand) + txt.print_ub(uw != twothousand1) + txt.print_ub(uw < twothousand1) + txt.print_ub(uw <= twothousand) + txt.print_ub(uw > nineteen99) + txt.print_ub(uw >= twothousand) + txt.spc() + txt.print_ub(f == f_minus_100) + txt.print_ub(f != f_minus_99) + txt.print_ub(f < f_minus_99) + txt.print_ub(f <= f_minus_100) + txt.print_ub(f > f_minus_101) + txt.print_ub(f >= f_minus_100) + txt.nl() + + txt.print("all 0: ") + txt.print_ub(b == minus_99) + txt.print_ub(b != minus_100) + txt.print_ub(b < minus_100) + txt.print_ub(b <= minus_101) + txt.print_ub(b > minus_100) + txt.print_ub(b >= minus_99) + txt.print_ub(ub ==twenty1) + txt.print_ub(ub !=twenty) + txt.print_ub(ub twenty) + txt.print_ub(ub>=twenty1) + txt.spc() + txt.print_ub(w == w_min_20001) + txt.print_ub(w != w_min_20000) + txt.print_ub(w < w_min_20000) + txt.print_ub(w <= w_min_20001) + txt.print_ub(w > w_min_20000) + txt.print_ub(w >= w_min_19999) + txt.print_ub(uw == nineteen99) + txt.print_ub(uw != twothousand) + txt.print_ub(uw < twothousand) + txt.print_ub(uw <= nineteen99) + txt.print_ub(uw > twothousand) + txt.print_ub(uw >= twothousand1) + txt.spc() + txt.print_ub(f == f_minus_99) + txt.print_ub(f != f_minus_100) + txt.print_ub(f < f_minus_100) + txt.print_ub(f <= f_minus_101) + txt.print_ub(f > f_minus_100) + txt.print_ub(f >= f_minus_99) + txt.nl() + + txt.print("all .: ") + if b == minus_100 txt.chrout('.') + if b != minus_99 txt.chrout('.') + if b < minus_99 txt.chrout('.') + if b <= minus_100 txt.chrout('.') + if b > minus_101 txt.chrout('.') + if b >= minus_100 txt.chrout('.') + if ub == twenty txt.chrout('.') + if ub != nineteen txt.chrout('.') + if ub < twenty1 txt.chrout('.') + if ub <= twenty txt.chrout('.') + if ub> nineteen txt.chrout('.') + if ub>= twenty txt.chrout('.') + txt.spc() + if w == w_min_20000 txt.chrout('.') + if w != w_min_19999 txt.chrout('.') + if w < w_min_19999 txt.chrout('.') + if w <= w_min_20000 txt.chrout('.') + if w > w_min_20001 txt.chrout('.') + if w >= w_min_20000 txt.chrout('.') + if uw == twothousand txt.chrout('.') + if uw != twothousand1 txt.chrout('.') + if uw < twothousand1 txt.chrout('.') + if uw <= twothousand txt.chrout('.') + if uw > nineteen99 txt.chrout('.') + if uw >= twothousand txt.chrout('.') + txt.spc() + if f == f_minus_100 txt.chrout('.') + if f != f_minus_99 txt.chrout('.') + if f < f_minus_99 txt.chrout('.') + if f <= f_minus_100 txt.chrout('.') + if f > f_minus_101 txt.chrout('.') + if f >= f_minus_100 txt.chrout('.') + txt.nl() + + txt.print(" no !: ") + if b == minus_99 txt.chrout('!') + if b != minus_100 txt.chrout('!') + if b < minus_100 txt.chrout('!') + if b <= minus_101 txt.chrout('!') + if b > minus_100 txt.chrout('!') + if b >= minus_99 txt.chrout('!') + if ub == twenty1 txt.chrout('!') + if ub != twenty txt.chrout('!') + if ub < twenty txt.chrout('!') + if ub <= nineteen txt.chrout('!') + if ub> twenty txt.chrout('!') + if ub>= twenty1 txt.chrout('!') + txt.spc() + if w == w_min_20001 txt.chrout('!') + if w != w_min_20000 txt.chrout('!') + if w < w_min_20000 txt.chrout('!') + if w <= w_min_20001 txt.chrout('!') + if w > w_min_20000 txt.chrout('!') + if w >= w_min_19999 txt.chrout('!') + if uw == nineteen99 txt.chrout('!') + if uw != twothousand txt.chrout('!') + if uw < twothousand txt.chrout('!') + if uw <= nineteen99 txt.chrout('!') + if uw > twothousand txt.chrout('!') + if uw >= twothousand1 txt.chrout('!') + txt.spc() + if f == f_minus_99 txt.chrout('!') + if f != f_minus_100 txt.chrout('!') + if f < f_minus_100 txt.chrout('!') + if f <= f_minus_101 txt.chrout('!') + if f > f_minus_100 txt.chrout('!') + if f >= f_minus_99 txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == minus_100 txt.chrout('.') else txt.chrout('!') + if b != minus_99 txt.chrout('.') else txt.chrout('!') + if b < minus_99 txt.chrout('.') else txt.chrout('!') + if b <= minus_100 txt.chrout('.') else txt.chrout('!') + if b > minus_101 txt.chrout('.') else txt.chrout('!') + if b >= minus_100 txt.chrout('.') else txt.chrout('!') + if ub == twenty txt.chrout('.') else txt.chrout('!') + if ub != nineteen txt.chrout('.') else txt.chrout('!') + if ub < twenty1 txt.chrout('.') else txt.chrout('!') + if ub <= twenty txt.chrout('.') else txt.chrout('!') + if ub> nineteen txt.chrout('.') else txt.chrout('!') + if ub>=twenty txt.chrout('.') else txt.chrout('!') + txt.spc() + if w == w_min_20000 txt.chrout('.') else txt.chrout('!') + if w != w_min_19999 txt.chrout('.') else txt.chrout('!') + if w < w_min_19999 txt.chrout('.') else txt.chrout('!') + if w <= w_min_20000 txt.chrout('.') else txt.chrout('!') + if w > w_min_20001 txt.chrout('.') else txt.chrout('!') + if w >= w_min_20000 txt.chrout('.') else txt.chrout('!') + if uw == twothousand txt.chrout('.') else txt.chrout('!') + if uw != twothousand1 txt.chrout('.') else txt.chrout('!') + if uw < twothousand1 txt.chrout('.') else txt.chrout('!') + if uw <= twothousand txt.chrout('.') else txt.chrout('!') + if uw > nineteen99 txt.chrout('.') else txt.chrout('!') + if uw >= twothousand txt.chrout('.') else txt.chrout('!') + txt.spc() + if f == f_minus_100 txt.chrout('.') else txt.chrout('!') + if f != f_minus_99 txt.chrout('.') else txt.chrout('!') + if f < f_minus_99 txt.chrout('.') else txt.chrout('!') + if f <= f_minus_100 txt.chrout('.') else txt.chrout('!') + if f > f_minus_101 txt.chrout('.') else txt.chrout('!') + if f >= f_minus_100 txt.chrout('.') else txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == minus_99 txt.chrout('!') else txt.chrout('.') + if b != minus_100 txt.chrout('!') else txt.chrout('.') + if b < minus_100 txt.chrout('!') else txt.chrout('.') + if b <= minus_101 txt.chrout('!') else txt.chrout('.') + if b > minus_100 txt.chrout('!') else txt.chrout('.') + if b >= minus_99 txt.chrout('!') else txt.chrout('.') + if ub == twenty1 txt.chrout('!') else txt.chrout('.') + if ub !=twenty txt.chrout('!') else txt.chrout('.') + if ub twenty txt.chrout('!') else txt.chrout('.') + if ub>= twenty1 txt.chrout('!') else txt.chrout('.') + txt.spc() + if w == w_min_20001 txt.chrout('!') else txt.chrout('.') + if w != w_min_20000 txt.chrout('!') else txt.chrout('.') + if w < w_min_20000 txt.chrout('!') else txt.chrout('.') + if w <= w_min_20001 txt.chrout('!') else txt.chrout('.') + if w > w_min_20000 txt.chrout('!') else txt.chrout('.') + if w >= w_min_19999 txt.chrout('!') else txt.chrout('.') + if uw == nineteen99 txt.chrout('!') else txt.chrout('.') + if uw != twothousand txt.chrout('!') else txt.chrout('.') + if uw < twothousand txt.chrout('!') else txt.chrout('.') + if uw <= nineteen99 txt.chrout('!') else txt.chrout('.') + if uw > twothousand txt.chrout('!') else txt.chrout('.') + if uw >= twothousand1 txt.chrout('!') else txt.chrout('.') + txt.spc() + if f == f_minus_99 txt.chrout('!') else txt.chrout('.') + if f != f_minus_100 txt.chrout('!') else txt.chrout('.') + if f < f_minus_100 txt.chrout('!') else txt.chrout('.') + if f <= f_minus_101 txt.chrout('!') else txt.chrout('.') + if f > f_minus_100 txt.chrout('!') else txt.chrout('.') + if f >= f_minus_99 txt.chrout('!') else txt.chrout('.') + txt.nl() + + + b = minus_100 + while b <= minus_20 + b++ + txt.print_b(b) + txt.print(" -19\n") + b = minus_100 + while b < -minus_20 + b++ + txt.print_b(b) + txt.print(" -20\n") + + ub = 20 + while ub <= twohundred + ub++ + txt.print_ub(ub) + txt.print(" 201\n") + ub = 20 + while ub < twohundred + ub++ + txt.print_ub(ub) + txt.print(" 200\n") + + w = w_min_20000 + while w <= minus8000 { + w++ + } + txt.print_w(w) + txt.print(" -7999\n") + w = w_min_20000 + while w < minus8000 { + w++ + } + txt.print_w(w) + txt.print(" -8000\n") + + uw = 2000 + while uw <= eightthousand { + uw++ + } + txt.print_uw(uw) + txt.print(" 8001\n") + uw = 2000 + while uw < eightthousand { + uw++ + } + txt.print_uw(uw) + txt.print(" 8000\n") + + f = 0.0 + floats.print_f(f) + while f -101) -; txt.print_ub(b >= -100) -; txt.print_ub(ub ==20) -; txt.print_ub(ub !=19) -; txt.print_ub(ub <21) -; txt.print_ub(ub <=20) -; txt.print_ub(ub>19) -; txt.print_ub(ub>=20) -; txt.spc() -; txt.print_ub(w == -20000) -; txt.print_ub(w != -19999) -; txt.print_ub(w < -19999) -; txt.print_ub(w <= -20000) -; txt.print_ub(w > -20001) -; txt.print_ub(w >= -20000) -; txt.print_ub(uw == 2000) -; txt.print_ub(uw != 2001) -; txt.print_ub(uw < 2001) -; txt.print_ub(uw <= 2000) -; txt.print_ub(uw > 1999) -; txt.print_ub(uw >= 2000) -; txt.spc() -; txt.print_ub(f == -100.0) -; txt.print_ub(f != -99.0) -; txt.print_ub(f < -99.0) -; txt.print_ub(f <= -100.0) -; txt.print_ub(f > -101.0) -; txt.print_ub(f >= -100.0) -; txt.nl() -; -; txt.print("all 0: ") -; txt.print_ub(b == -99) -; txt.print_ub(b != -100) -; txt.print_ub(b < -100) -; txt.print_ub(b <= -101) -; txt.print_ub(b > -100) -; txt.print_ub(b >= -99) -; txt.print_ub(ub ==21) -; txt.print_ub(ub !=20) -; txt.print_ub(ub <20) -; txt.print_ub(ub <=19) -; txt.print_ub(ub>20) -; txt.print_ub(ub>=21) -; txt.spc() -; txt.print_ub(w == -20001) -; txt.print_ub(w != -20000) -; txt.print_ub(w < -20000) -; txt.print_ub(w <= -20001) -; txt.print_ub(w > -20000) -; txt.print_ub(w >= -19999) -; txt.print_ub(uw == 1999) -; txt.print_ub(uw != 2000) -; txt.print_ub(uw < 2000) -; txt.print_ub(uw <= 1999) -; txt.print_ub(uw > 2000) -; txt.print_ub(uw >= 2001) -; txt.spc() -; txt.print_ub(f == -99.0) -; txt.print_ub(f != -100.0) -; txt.print_ub(f < -100.0) -; txt.print_ub(f <= -101.0) -; txt.print_ub(f > -100.0) -; txt.print_ub(f >= -99.0) -; txt.nl() -; -; ; TODO ALL OF THE ABOVE BUT WITH A VARIABLE INSTEAD OF A CONST VALUE -; -; -; b = -100 -; while b <= -20 -; b++ -; txt.print_b(b) -; txt.print(" -19\n") -; b = -100 -; while b < -20 -; b++ -; txt.print_b(b) -; txt.print(" -20\n") -; -; ub = 20 -; while ub <= 200 -; ub++ -; txt.print_ub(ub) -; txt.print(" 201\n") -; ub = 20 -; while ub < 200 -; ub++ -; txt.print_ub(ub) -; txt.print(" 200\n") -; -; w = -20000 -; while w <= -8000 { -; w++ -; } -; txt.print_w(w) -; txt.print(" -7999\n") -; w = -20000 -; while w < -8000 { -; w++ -; } -; txt.print_w(w) -; txt.print(" -8000\n") -; -; uw = 2000 -; while uw <= 8000 { -; uw++ -; } -; txt.print_uw(uw) -; txt.print(" 8001\n") -; uw = 2000 -; while uw < 8000 { -; uw++ -; } -; txt.print_uw(uw) -; txt.print(" 8000\n") -; -; f = 0.0 -; while f<2.2 { -; f+=0.1 -; } -; floats.print_f(f) -; txt.print(" 2.2\n") + sub test_compare_literal() { + byte b = -100 + ubyte ub = 20 + word w = -20000 + uword uw = 2000 + float f = -100 + + txt.print("all 1: ") + txt.print_ub(b == -100) + txt.print_ub(b != -99) + txt.print_ub(b < -99) + txt.print_ub(b <= -100) + txt.print_ub(b > -101) + txt.print_ub(b >= -100) + txt.print_ub(ub ==20) + txt.print_ub(ub !=19) + txt.print_ub(ub <21) + txt.print_ub(ub <=20) + txt.print_ub(ub>19) + txt.print_ub(ub>=20) + txt.spc() + txt.print_ub(w == -20000) + txt.print_ub(w != -19999) + txt.print_ub(w < -19999) + txt.print_ub(w <= -20000) + txt.print_ub(w > -20001) + txt.print_ub(w >= -20000) + txt.print_ub(uw == 2000) + txt.print_ub(uw != 2001) + txt.print_ub(uw < 2001) + txt.print_ub(uw <= 2000) + txt.print_ub(uw > 1999) + txt.print_ub(uw >= 2000) + txt.spc() + txt.print_ub(f == -100.0) + txt.print_ub(f != -99.0) + txt.print_ub(f < -99.0) + txt.print_ub(f <= -100.0) + txt.print_ub(f > -101.0) + txt.print_ub(f >= -100.0) + txt.nl() + + txt.print("all 0: ") + txt.print_ub(b == -99) + txt.print_ub(b != -100) + txt.print_ub(b < -100) + txt.print_ub(b <= -101) + txt.print_ub(b > -100) + txt.print_ub(b >= -99) + txt.print_ub(ub ==21) + txt.print_ub(ub !=20) + txt.print_ub(ub <20) + txt.print_ub(ub <=19) + txt.print_ub(ub>20) + txt.print_ub(ub>=21) + txt.spc() + txt.print_ub(w == -20001) + txt.print_ub(w != -20000) + txt.print_ub(w < -20000) + txt.print_ub(w <= -20001) + txt.print_ub(w > -20000) + txt.print_ub(w >= -19999) + txt.print_ub(uw == 1999) + txt.print_ub(uw != 2000) + txt.print_ub(uw < 2000) + txt.print_ub(uw <= 1999) + txt.print_ub(uw > 2000) + txt.print_ub(uw >= 2001) + txt.spc() + txt.print_ub(f == -99.0) + txt.print_ub(f != -100.0) + txt.print_ub(f < -100.0) + txt.print_ub(f <= -101.0) + txt.print_ub(f > -100.0) + txt.print_ub(f >= -99.0) + txt.nl() + + txt.print("all .: ") + if b == -100 txt.chrout('.') + if b != -99 txt.chrout('.') + if b < -99 txt.chrout('.') + if b <= -100 txt.chrout('.') + if b > -101 txt.chrout('.') + if b >= -100 txt.chrout('.') + if ub ==20 txt.chrout('.') + if ub !=19 txt.chrout('.') + if ub <21 txt.chrout('.') + if ub <=20 txt.chrout('.') + if ub>19 txt.chrout('.') + if ub>=20 txt.chrout('.') + txt.spc() + if w == -20000 txt.chrout('.') + if w != -19999 txt.chrout('.') + if w < -19999 txt.chrout('.') + if w <= -20000 txt.chrout('.') + if w > -20001 txt.chrout('.') + if w >= -20000 txt.chrout('.') + if uw == 2000 txt.chrout('.') + if uw != 2001 txt.chrout('.') + if uw < 2001 txt.chrout('.') + if uw <= 2000 txt.chrout('.') + if uw > 1999 txt.chrout('.') + if uw >= 2000 txt.chrout('.') + txt.spc() + if f == -100.0 txt.chrout('.') + if f != -99.0 txt.chrout('.') + if f < -99.0 txt.chrout('.') + if f <= -100.0 txt.chrout('.') + if f > -101.0 txt.chrout('.') + if f >= -100.0 txt.chrout('.') + txt.nl() + + txt.print(" no !: ") + if b == -99 txt.chrout('!') + if b != -100 txt.chrout('!') + if b < -100 txt.chrout('!') + if b <= -101 txt.chrout('!') + if b > -100 txt.chrout('!') + if b >= -99 txt.chrout('!') + if ub ==21 txt.chrout('!') + if ub !=20 txt.chrout('!') + if ub <20 txt.chrout('!') + if ub <=19 txt.chrout('!') + if ub>20 txt.chrout('!') + if ub>=21 txt.chrout('!') + txt.spc() + if w == -20001 txt.chrout('!') + if w != -20000 txt.chrout('!') + if w < -20000 txt.chrout('!') + if w <= -20001 txt.chrout('!') + if w > -20000 txt.chrout('!') + if w >= -19999 txt.chrout('!') + if uw == 1999 txt.chrout('!') + if uw != 2000 txt.chrout('!') + if uw < 2000 txt.chrout('!') + if uw <= 1999 txt.chrout('!') + if uw > 2000 txt.chrout('!') + if uw >= 2001 txt.chrout('!') + txt.spc() + if f == -99.0 txt.chrout('!') + if f != -100.0 txt.chrout('!') + if f < -100.0 txt.chrout('!') + if f <= -101.0 txt.chrout('!') + if f > -100.0 txt.chrout('!') + if f >= -99.0 txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == -100 txt.chrout('.') else txt.chrout('!') + if b != -99 txt.chrout('.') else txt.chrout('!') + if b < -99 txt.chrout('.') else txt.chrout('!') + if b <= -100 txt.chrout('.') else txt.chrout('!') + if b > -101 txt.chrout('.') else txt.chrout('!') + if b >= -100 txt.chrout('.') else txt.chrout('!') + if ub ==20 txt.chrout('.') else txt.chrout('!') + if ub !=19 txt.chrout('.') else txt.chrout('!') + if ub <21 txt.chrout('.') else txt.chrout('!') + if ub <=20 txt.chrout('.') else txt.chrout('!') + if ub>19 txt.chrout('.') else txt.chrout('!') + if ub>=20 txt.chrout('.') else txt.chrout('!') + txt.spc() + if w == -20000 txt.chrout('.') else txt.chrout('!') + if w != -19999 txt.chrout('.') else txt.chrout('!') + if w < -19999 txt.chrout('.') else txt.chrout('!') + if w <= -20000 txt.chrout('.') else txt.chrout('!') + if w > -20001 txt.chrout('.') else txt.chrout('!') + if w >= -20000 txt.chrout('.') else txt.chrout('!') + if uw == 2000 txt.chrout('.') else txt.chrout('!') + if uw != 2001 txt.chrout('.') else txt.chrout('!') + if uw < 2001 txt.chrout('.') else txt.chrout('!') + if uw <= 2000 txt.chrout('.') else txt.chrout('!') + if uw > 1999 txt.chrout('.') else txt.chrout('!') + if uw >= 2000 txt.chrout('.') else txt.chrout('!') + txt.spc() + if f == -100.0 txt.chrout('.') else txt.chrout('!') + if f != -99.0 txt.chrout('.') else txt.chrout('!') + if f < -99.0 txt.chrout('.') else txt.chrout('!') + if f <= -100.0 txt.chrout('.') else txt.chrout('!') + if f > -101.0 txt.chrout('.') else txt.chrout('!') + if f >= -100.0 txt.chrout('.') else txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == -99 txt.chrout('!') else txt.chrout('.') + if b != -100 txt.chrout('!') else txt.chrout('.') + if b < -100 txt.chrout('!') else txt.chrout('.') + if b <= -101 txt.chrout('!') else txt.chrout('.') + if b > -100 txt.chrout('!') else txt.chrout('.') + if b >= -99 txt.chrout('!') else txt.chrout('.') + if ub ==21 txt.chrout('!') else txt.chrout('.') + if ub !=20 txt.chrout('!') else txt.chrout('.') + if ub <20 txt.chrout('!') else txt.chrout('.') + if ub <=19 txt.chrout('!') else txt.chrout('.') + if ub>20 txt.chrout('!') else txt.chrout('.') + if ub>=21 txt.chrout('!') else txt.chrout('.') + txt.spc() + if w == -20001 txt.chrout('!') else txt.chrout('.') + if w != -20000 txt.chrout('!') else txt.chrout('.') + if w < -20000 txt.chrout('!') else txt.chrout('.') + if w <= -20001 txt.chrout('!') else txt.chrout('.') + if w > -20000 txt.chrout('!') else txt.chrout('.') + if w >= -19999 txt.chrout('!') else txt.chrout('.') + if uw == 1999 txt.chrout('!') else txt.chrout('.') + if uw != 2000 txt.chrout('!') else txt.chrout('.') + if uw < 2000 txt.chrout('!') else txt.chrout('.') + if uw <= 1999 txt.chrout('!') else txt.chrout('.') + if uw > 2000 txt.chrout('!') else txt.chrout('.') + if uw >= 2001 txt.chrout('!') else txt.chrout('.') + txt.spc() + if f == -99.0 txt.chrout('!') else txt.chrout('.') + if f != -100.0 txt.chrout('!') else txt.chrout('.') + if f < -100.0 txt.chrout('!') else txt.chrout('.') + if f <= -101.0 txt.chrout('!') else txt.chrout('.') + if f > -100.0 txt.chrout('!') else txt.chrout('.') + if f >= -99.0 txt.chrout('!') else txt.chrout('.') + txt.nl() + + + b = -100 + while b <= -20 + b++ + txt.print_b(b) + txt.print(" -19\n") + b = -100 + while b < -20 + b++ + txt.print_b(b) + txt.print(" -20\n") + + ub = 20 + while ub <= 200 + ub++ + txt.print_ub(ub) + txt.print(" 201\n") + ub = 20 + while ub < 200 + ub++ + txt.print_ub(ub) + txt.print(" 200\n") + + w = -20000 + while w <= -8000 { + w++ + } + txt.print_w(w) + txt.print(" -7999\n") + w = -20000 + while w < -8000 { + w++ + } + txt.print_w(w) + txt.print(" -8000\n") + + uw = 2000 + while uw <= 8000 { + uw++ + } + txt.print_uw(uw) + txt.print(" 8001\n") + uw = 2000 + while uw < 8000 { + uw++ + } + txt.print_uw(uw) + txt.print(" 8000\n") + + f = 0.0 + floats.print_f(f) + while f<2.2 { + f+=0.1 + floats.print_f(f) + } + floats.print_f(f) + txt.print(" 2.2\n") + } + + sub test_compare_variable() { + byte b = -100 + ubyte ub = 20 + word w = -20000 + uword uw = 2000 + float f = -100 + + byte minus_100 = -100 + byte minus_99 = -99 + byte minus_20 = -20 + byte minus_101 = -101 + ubyte nineteen = 19 + ubyte twenty = 20 + ubyte twenty1 = 21 + ubyte twohundred = 200 + float f_minus_100 = -100.0 + float f_minus_101 = -101.0 + float f_minus_99 = -99.0 + float twodottwo = 2.2 + word minus8000 = -8000 + word eightthousand = 8000 + word w_min_20000 = -20000 + word w_min_19999 = -19999 + word w_min_20001 = -20001 + uword twothousand = 2000 + uword twothousand1 = 2001 + uword nineteen99 = 1999 + + + txt.print("all 1: ") + txt.print_ub(b == minus_100) + txt.print_ub(b != minus_99) + txt.print_ub(b < minus_99) + txt.print_ub(b <= minus_100) + txt.print_ub(b > minus_101) + txt.print_ub(b >= minus_100) + txt.print_ub(ub ==twenty) + txt.print_ub(ub !=nineteen) + txt.print_ub(ub nineteen) + txt.print_ub(ub>=twenty) + txt.spc() + txt.print_ub(w == w_min_20000) + txt.print_ub(w != w_min_19999) + txt.print_ub(w < w_min_19999) + txt.print_ub(w <= w_min_20000) + txt.print_ub(w > w_min_20001) + txt.print_ub(w >= w_min_20000) + txt.print_ub(uw == twothousand) + txt.print_ub(uw != twothousand1) + txt.print_ub(uw < twothousand1) + txt.print_ub(uw <= twothousand) + txt.print_ub(uw > nineteen99) + txt.print_ub(uw >= twothousand) + txt.spc() + txt.print_ub(f == f_minus_100) + txt.print_ub(f != f_minus_99) + txt.print_ub(f < f_minus_99) + txt.print_ub(f <= f_minus_100) + txt.print_ub(f > f_minus_101) + txt.print_ub(f >= f_minus_100) + txt.nl() + + txt.print("all 0: ") + txt.print_ub(b == minus_99) + txt.print_ub(b != minus_100) + txt.print_ub(b < minus_100) + txt.print_ub(b <= minus_101) + txt.print_ub(b > minus_100) + txt.print_ub(b >= minus_99) + txt.print_ub(ub ==twenty1) + txt.print_ub(ub !=twenty) + txt.print_ub(ub twenty) + txt.print_ub(ub>=twenty1) + txt.spc() + txt.print_ub(w == w_min_20001) + txt.print_ub(w != w_min_20000) + txt.print_ub(w < w_min_20000) + txt.print_ub(w <= w_min_20001) + txt.print_ub(w > w_min_20000) + txt.print_ub(w >= w_min_19999) + txt.print_ub(uw == nineteen99) + txt.print_ub(uw != twothousand) + txt.print_ub(uw < twothousand) + txt.print_ub(uw <= nineteen99) + txt.print_ub(uw > twothousand) + txt.print_ub(uw >= twothousand1) + txt.spc() + txt.print_ub(f == f_minus_99) + txt.print_ub(f != f_minus_100) + txt.print_ub(f < f_minus_100) + txt.print_ub(f <= f_minus_101) + txt.print_ub(f > f_minus_100) + txt.print_ub(f >= f_minus_99) + txt.nl() + + txt.print("all .: ") + if b == minus_100 txt.chrout('.') + if b != minus_99 txt.chrout('.') + if b < minus_99 txt.chrout('.') + if b <= minus_100 txt.chrout('.') + if b > minus_101 txt.chrout('.') + if b >= minus_100 txt.chrout('.') + if ub == twenty txt.chrout('.') + if ub != nineteen txt.chrout('.') + if ub < twenty1 txt.chrout('.') + if ub <= twenty txt.chrout('.') + if ub> nineteen txt.chrout('.') + if ub>= twenty txt.chrout('.') + txt.spc() + if w == w_min_20000 txt.chrout('.') + if w != w_min_19999 txt.chrout('.') + if w < w_min_19999 txt.chrout('.') + if w <= w_min_20000 txt.chrout('.') + if w > w_min_20001 txt.chrout('.') + if w >= w_min_20000 txt.chrout('.') + if uw == twothousand txt.chrout('.') + if uw != twothousand1 txt.chrout('.') + if uw < twothousand1 txt.chrout('.') + if uw <= twothousand txt.chrout('.') + if uw > nineteen99 txt.chrout('.') + if uw >= twothousand txt.chrout('.') + txt.spc() + if f == f_minus_100 txt.chrout('.') + if f != f_minus_99 txt.chrout('.') + if f < f_minus_99 txt.chrout('.') + if f <= f_minus_100 txt.chrout('.') + if f > f_minus_101 txt.chrout('.') + if f >= f_minus_100 txt.chrout('.') + txt.nl() + + txt.print(" no !: ") + if b == minus_99 txt.chrout('!') + if b != minus_100 txt.chrout('!') + if b < minus_100 txt.chrout('!') + if b <= minus_101 txt.chrout('!') + if b > minus_100 txt.chrout('!') + if b >= minus_99 txt.chrout('!') + if ub == twenty1 txt.chrout('!') + if ub != twenty txt.chrout('!') + if ub < twenty txt.chrout('!') + if ub <= nineteen txt.chrout('!') + if ub> twenty txt.chrout('!') + if ub>= twenty1 txt.chrout('!') + txt.spc() + if w == w_min_20001 txt.chrout('!') + if w != w_min_20000 txt.chrout('!') + if w < w_min_20000 txt.chrout('!') + if w <= w_min_20001 txt.chrout('!') + if w > w_min_20000 txt.chrout('!') + if w >= w_min_19999 txt.chrout('!') + if uw == nineteen99 txt.chrout('!') + if uw != twothousand txt.chrout('!') + if uw < twothousand txt.chrout('!') + if uw <= nineteen99 txt.chrout('!') + if uw > twothousand txt.chrout('!') + if uw >= twothousand1 txt.chrout('!') + txt.spc() + if f == f_minus_99 txt.chrout('!') + if f != f_minus_100 txt.chrout('!') + if f < f_minus_100 txt.chrout('!') + if f <= f_minus_101 txt.chrout('!') + if f > f_minus_100 txt.chrout('!') + if f >= f_minus_99 txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == minus_100 txt.chrout('.') else txt.chrout('!') + if b != minus_99 txt.chrout('.') else txt.chrout('!') + if b < minus_99 txt.chrout('.') else txt.chrout('!') + if b <= minus_100 txt.chrout('.') else txt.chrout('!') + if b > minus_101 txt.chrout('.') else txt.chrout('!') + if b >= minus_100 txt.chrout('.') else txt.chrout('!') + if ub == twenty txt.chrout('.') else txt.chrout('!') + if ub != nineteen txt.chrout('.') else txt.chrout('!') + if ub < twenty1 txt.chrout('.') else txt.chrout('!') + if ub <= twenty txt.chrout('.') else txt.chrout('!') + if ub> nineteen txt.chrout('.') else txt.chrout('!') + if ub>=twenty txt.chrout('.') else txt.chrout('!') + txt.spc() + if w == w_min_20000 txt.chrout('.') else txt.chrout('!') + if w != w_min_19999 txt.chrout('.') else txt.chrout('!') + if w < w_min_19999 txt.chrout('.') else txt.chrout('!') + if w <= w_min_20000 txt.chrout('.') else txt.chrout('!') + if w > w_min_20001 txt.chrout('.') else txt.chrout('!') + if w >= w_min_20000 txt.chrout('.') else txt.chrout('!') + if uw == twothousand txt.chrout('.') else txt.chrout('!') + if uw != twothousand1 txt.chrout('.') else txt.chrout('!') + if uw < twothousand1 txt.chrout('.') else txt.chrout('!') + if uw <= twothousand txt.chrout('.') else txt.chrout('!') + if uw > nineteen99 txt.chrout('.') else txt.chrout('!') + if uw >= twothousand txt.chrout('.') else txt.chrout('!') + txt.spc() + if f == f_minus_100 txt.chrout('.') else txt.chrout('!') + if f != f_minus_99 txt.chrout('.') else txt.chrout('!') + if f < f_minus_99 txt.chrout('.') else txt.chrout('!') + if f <= f_minus_100 txt.chrout('.') else txt.chrout('!') + if f > f_minus_101 txt.chrout('.') else txt.chrout('!') + if f >= f_minus_100 txt.chrout('.') else txt.chrout('!') + txt.nl() + + txt.print("all .: ") + if b == minus_99 txt.chrout('!') else txt.chrout('.') + if b != minus_100 txt.chrout('!') else txt.chrout('.') + if b < minus_100 txt.chrout('!') else txt.chrout('.') + if b <= minus_101 txt.chrout('!') else txt.chrout('.') + if b > minus_100 txt.chrout('!') else txt.chrout('.') + if b >= minus_99 txt.chrout('!') else txt.chrout('.') + if ub == twenty1 txt.chrout('!') else txt.chrout('.') + if ub !=twenty txt.chrout('!') else txt.chrout('.') + if ub twenty txt.chrout('!') else txt.chrout('.') + if ub>= twenty1 txt.chrout('!') else txt.chrout('.') + txt.spc() + if w == w_min_20001 txt.chrout('!') else txt.chrout('.') + if w != w_min_20000 txt.chrout('!') else txt.chrout('.') + if w < w_min_20000 txt.chrout('!') else txt.chrout('.') + if w <= w_min_20001 txt.chrout('!') else txt.chrout('.') + if w > w_min_20000 txt.chrout('!') else txt.chrout('.') + if w >= w_min_19999 txt.chrout('!') else txt.chrout('.') + if uw == nineteen99 txt.chrout('!') else txt.chrout('.') + if uw != twothousand txt.chrout('!') else txt.chrout('.') + if uw < twothousand txt.chrout('!') else txt.chrout('.') + if uw <= nineteen99 txt.chrout('!') else txt.chrout('.') + if uw > twothousand txt.chrout('!') else txt.chrout('.') + if uw >= twothousand1 txt.chrout('!') else txt.chrout('.') + txt.spc() + if f == f_minus_99 txt.chrout('!') else txt.chrout('.') + if f != f_minus_100 txt.chrout('!') else txt.chrout('.') + if f < f_minus_100 txt.chrout('!') else txt.chrout('.') + if f <= f_minus_101 txt.chrout('!') else txt.chrout('.') + if f > f_minus_100 txt.chrout('!') else txt.chrout('.') + if f >= f_minus_99 txt.chrout('!') else txt.chrout('.') + txt.nl() + + + b = minus_100 + while b <= minus_20 + b++ + txt.print_b(b) + txt.print(" -19\n") + b = minus_100 + while b < -minus_20 + b++ + txt.print_b(b) + txt.print(" -20\n") + + ub = 20 + while ub <= twohundred + ub++ + txt.print_ub(ub) + txt.print(" 201\n") + ub = 20 + while ub < twohundred + ub++ + txt.print_ub(ub) + txt.print(" 200\n") + + w = w_min_20000 + while w <= minus8000 { + w++ + } + txt.print_w(w) + txt.print(" -7999\n") + w = w_min_20000 + while w < minus8000 { + w++ + } + txt.print_w(w) + txt.print(" -8000\n") + + uw = 2000 + while uw <= eightthousand { + uw++ + } + txt.print_uw(uw) + txt.print(" 8001\n") + uw = 2000 + while uw < eightthousand { + uw++ + } + txt.print_uw(uw) + txt.print(" 8000\n") + + f = 0.0 + floats.print_f(f) + while f