diff --git a/compiler/test/TestNumbers.kt b/compiler/test/TestNumbers.kt index f7a3f355f..5157f00a5 100644 --- a/compiler/test/TestNumbers.kt +++ b/compiler/test/TestNumbers.kt @@ -6,10 +6,15 @@ import io.kotest.matchers.doubles.plusOrMinus import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import io.kotest.matchers.string.shouldContain +import prog8.ast.expressions.NumericLiteral +import prog8.ast.statements.Assignment +import prog8.code.core.DataType import prog8.code.core.InternalCompilerException +import prog8.code.core.Position import prog8.code.core.toHex import prog8.code.target.C64Target import prog8.code.target.cbm.Mflpt5 +import prog8.compiler.printProgram import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.compileText @@ -180,4 +185,27 @@ class TestNumbers: FunSpec({ """ compileText(C64Target(), true, src, writeAssembly = false) shouldNotBe null } + + test("signed negative numbers cast to unsigned allowed") { + val src=""" + main { + sub start() { + uword uw1 = -32768 + uword uw = -1 + ubyte ub = -1 + uw = -2 as uword + ub = -2 as ubyte + } + } + """ + val result = compileText(C64Target(), false, src, writeAssembly = false)!! + val statements = result.program.entrypoint.statements + statements.size shouldBe 8 + printProgram(result.program) + (statements[1] as Assignment).value shouldBe NumericLiteral(DataType.UWORD, 32768.0, Position.DUMMY) + (statements[3] as Assignment).value shouldBe NumericLiteral(DataType.UWORD, 65535.0, Position.DUMMY) + (statements[5] as Assignment).value shouldBe NumericLiteral(DataType.UBYTE, 255.0, Position.DUMMY) + (statements[6] as Assignment).value shouldBe NumericLiteral(DataType.UWORD, 65534.0, Position.DUMMY) + (statements[7] as Assignment).value shouldBe NumericLiteral(DataType.UBYTE, 254.0, Position.DUMMY) + } }) diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index 0b08a4e22..8f91cae85 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -565,17 +565,31 @@ class TestOptimization: FunSpec({ val src=""" main { sub start() { - ubyte @shared z1 = - 1 + ubyte @shared z1 = - 200 } } """ val errors = ErrorReporterForTests() - compileText(C64Target(), optimize=true, src, writeAssembly=false, errors = errors) shouldBe null + compileText(C64Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null errors.errors.size shouldBe 2 - errors.errors[0] shouldContain "type of value BYTE doesn't match target UBYTE" + errors.errors[0] shouldContain "type of value WORD doesn't match target UBYTE" errors.errors[1] shouldContain "out of range" } + test("out of range cast should give error") { + val src=""" + main { + sub start() { + ubyte @shared z1 = - 200 as ubyte + } + } + """ + val errors = ErrorReporterForTests() + compileText(C64Target(), optimize=false, src, writeAssembly=false, errors = errors) shouldBe null + errors.errors.size shouldBe 1 + errors.errors[0] shouldContain "can't cast" + } + test("test augmented expression asmgen") { val src = """ main { diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 11338a502..e21a92df7 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -541,10 +541,18 @@ class NumericLiteral(val type: DataType, // only numerical types allowed return CastValue(true, NumericLiteral(targettype, number, position)) } DataType.BYTE -> { - if(targettype== DataType.UBYTE && number >= 0) - return CastValue(true, NumericLiteral(targettype, number, position)) - if(targettype== DataType.UWORD && number >= 0) - return CastValue(true, NumericLiteral(targettype, number, position)) + if(targettype== DataType.UBYTE) { + if(number in -128.0..0.0) + return CastValue(true, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position)) + else if(number in 0.0..255.0) + return CastValue(true, NumericLiteral(targettype, number, position)) + } + if(targettype== DataType.UWORD) { + if(number in -32768.0..0.0) + return CastValue(true, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position)) + else if(number in 0.0..65535.0) + return CastValue(true, NumericLiteral(targettype, number, position)) + } if(targettype== DataType.WORD) return CastValue(true, NumericLiteral(targettype, number, position)) if(targettype== DataType.FLOAT) @@ -563,10 +571,18 @@ class NumericLiteral(val type: DataType, // only numerical types allowed DataType.WORD -> { if(targettype== DataType.BYTE && number >= -128 && number <=127) return CastValue(true, NumericLiteral(targettype, number, position)) - if(targettype== DataType.UBYTE && number >= 0 && number <= 255) - return CastValue(true, NumericLiteral(targettype, number, position)) - if(targettype== DataType.UWORD && number >=0) - return CastValue(true, NumericLiteral(targettype, number, position)) + if(targettype== DataType.UBYTE) { + if(number in -128.0..0.0) + return CastValue(true, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position)) + else if(number in 0.0..255.0) + return CastValue(true, NumericLiteral(targettype, number, position)) + } + if(targettype== DataType.UWORD) { + if(number in -32768.0 .. 0.0) + return CastValue(true, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position)) + else if(number in 0.0..65535.0) + return CastValue(true, NumericLiteral(targettype, number, position)) + } if(targettype== DataType.FLOAT) return CastValue(true, NumericLiteral(targettype, number, position)) } diff --git a/examples/test.p8 b/examples/test.p8 index 40281a10e..2ca8e7bad 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,5 +1,5 @@ %import textio -%import test_stack +;%import test_stack %zeropage basicsafe @@ -31,8 +31,16 @@ main { sub start() { ; mcCarthy() - test_stack.test() + uword uw = -2 + ubyte ub = -2 + uw = -2 as uword + ub = -2 as ubyte + txt.print_uw(uw) + txt.spc() + txt.print_ub(ub) + txt.nl() + ;test_stack.test() ubyte value = 0 ubyte one = 1 @@ -93,7 +101,7 @@ main { } txt.nl() - test_stack.test() + ;test_stack.test() ; ; a "pixelshader":