From 242a3eec635cda0613cb2d4ade95b2e78f712f79 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 3 Jan 2024 21:46:22 +0100 Subject: [PATCH] fix data type difference error on range from and to values --- codeCore/src/prog8/code/optimize/Optimizer.kt | 3 +- .../cpu6502/assignment/AnyExprAsmGen.kt | 2 +- .../astprocessing/IntermediateAstMaker.kt | 2 + .../compiler/astprocessing/TypecastsAdder.kt | 11 +++++ compiler/test/TestCompilerOnRanges.kt | 17 +++++++ examples/test.p8 | 49 +++---------------- 6 files changed, 39 insertions(+), 45 deletions(-) diff --git a/codeCore/src/prog8/code/optimize/Optimizer.kt b/codeCore/src/prog8/code/optimize/Optimizer.kt index c316ea5f0..dd3606be1 100644 --- a/codeCore/src/prog8/code/optimize/Optimizer.kt +++ b/codeCore/src/prog8/code/optimize/Optimizer.kt @@ -62,6 +62,7 @@ private fun optimizeCommonSubExpressions(program: PtProgram, errors: IErrorRepor } // replace common subexpressions by a temp variable that is assigned only once. + // TODO: check for commonalities across multiple separate expressions in the current scope, not only inside a single line commons.forEach { binexpr, (occurrence1, occurrence2) -> val (stmtContainer, stmt) = findContainingStatements(binexpr) val occurrence1idx = occurrence1.parent.children.indexOf(occurrence1) @@ -92,7 +93,7 @@ private fun optimizeCommonSubExpressions(program: PtProgram, errors: IErrorRepor stmtContainer.add(0, tempvar) tempvar.parent = stmtContainer - errors.info("common subexpressions replaced by a tempvar, maybe simplify the expression manually", binexpr.position) + // errors.info("common subexpressions replaced by a tempvar, maybe simplify the expression manually", binexpr.position) } return commons.size diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt index 956f47883..baf267300 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AnyExprAsmGen.kt @@ -29,7 +29,7 @@ internal class AnyExprAsmGen( require(expr.operator in ComparisonOperators) return assignFloatBinExpr(expr, assign) } - throw AssemblyError("weird expr operand types: ${expr.left.type} and {${expr.right.type}") + throw AssemblyError("weird expr operand types: ${expr.left.type} and ${expr.right.type}") } in WordDatatypes -> { require(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) { diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index 2089002c9..d3436066a 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -586,6 +586,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr private fun transform(srcCheck: ContainmentCheck): PtExpression { fun desugar(range: RangeExpression): PtExpression { + require(range.from.inferType(program)==range.to.inferType(program)) val expr = PtBinaryExpression("and", DataType.UBYTE, srcCheck.position) val x1 = transformExpression(srcCheck.element) val x2 = transformExpression(srcCheck.element) @@ -674,6 +675,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr } private fun transform(srcRange: RangeExpression): PtRange { + require(srcRange.from.inferType(program)==srcRange.to.inferType(program)) val type = srcRange.inferType(program).getOrElse { throw FatalAstException("unknown dt") } val range=PtRange(type, srcRange.position) range.add(transformExpression(srcRange.from)) diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index bc7ad4f8e..b544e875c 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -378,6 +378,17 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val return noModifications } + override fun after(range: RangeExpression, parent: Node): Iterable { + val fromDt = range.from.inferType(program).getOr(DataType.UNDEFINED) + val toDt = range.to.inferType(program).getOr(DataType.UNDEFINED) + val modifications = mutableListOf() + val (commonDt, toChange) = BinaryExpression.commonDatatype(fromDt, toDt, range.from, range.to) + if(toChange!=null) + addTypecastOrCastedValueModification(modifications, toChange, commonDt, range) + return modifications + } + + private fun addTypecastOrCastedValueModification( modifications: MutableList, expressionToCast: Expression, diff --git a/compiler/test/TestCompilerOnRanges.kt b/compiler/test/TestCompilerOnRanges.kt index c23ab01f3..fe5480e04 100644 --- a/compiler/test/TestCompilerOnRanges.kt +++ b/compiler/test/TestCompilerOnRanges.kt @@ -440,4 +440,21 @@ class TestCompilerOnRanges: FunSpec({ } }""", writeAssembly = true) shouldNotBe null } + + test("ranges with byte and word boundary") { + val src=""" +main{ + sub start() { + cx16.r0 = 500 + if cx16.r0 in 127 to 5555 + cx16.r0++ + + cx16.r0 = 50 + if cx16.r0 in 5555 downto 127 + cx16.r0++ + } +} + """ + compileText(Cx16Target(), true, src, writeAssembly = true) shouldNotBe null + } }) diff --git a/examples/test.p8 b/examples/test.p8 index c746a1a5c..4f0b24036 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,54 +1,17 @@ %import textio -%import floats %zeropage basicsafe main { sub start() { - ubyte [] array = 100 to 110 - for cx16.r0L in array { - txt.print_ub(cx16.r0L) - txt.spc() - } - txt.nl() + cx16.r0 = 500 + if cx16.r0 in 127 to 5555 + cx16.r0++ - ubyte x = 14 - if x in 10 to 20 { - txt.print("yep1\n") - } - if x in 20 to 30 { - txt.print("yep2\n") - } - if x in 10 to 20 step 2 { - txt.print("yep1b\n") - } - if x in 20 to 30 step 2 { - txt.print("yep2b\n") - } + cx16.r0 = 50 + if cx16.r0 in 5555 downto 127 + cx16.r0++ - if x in 20 to 10 step -2 { - txt.print("yep1c\n") - } - if x in 30 to 20 step -2 { - txt.print("yep2c\n") - } - - txt.nl() - - ubyte @shared y = 12 - if y in 10 to 20 { - txt.print("yep1\n") - } - if y in 20 to 30 { - txt.print("yep2\n") - } - - if y in 20 downto 10 { - txt.print("yep1c\n") - } - if y in 30 downto 20 { - txt.print("yep2c\n") - } } }