allow casting negative numbers to unsigned, result = 2's complement

This commit is contained in:
Irmen de Jong 2022-06-05 14:21:10 +02:00
parent 8f1c86f550
commit 031f647952
4 changed files with 80 additions and 14 deletions

View File

@ -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)
}
})

View File

@ -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 {

View File

@ -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))
}

View File

@ -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":