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.shouldBe
import io.kotest.matchers.shouldNotBe import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain 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.InternalCompilerException
import prog8.code.core.Position
import prog8.code.core.toHex import prog8.code.core.toHex
import prog8.code.target.C64Target import prog8.code.target.C64Target
import prog8.code.target.cbm.Mflpt5 import prog8.code.target.cbm.Mflpt5
import prog8.compiler.printProgram
import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.compileText import prog8tests.helpers.compileText
@ -180,4 +185,27 @@ class TestNumbers: FunSpec({
""" """
compileText(C64Target(), true, src, writeAssembly = false) shouldNotBe null 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=""" val src="""
main { main {
sub start() { sub start() {
ubyte @shared z1 = - 1 ubyte @shared z1 = - 200
} }
} }
""" """
val errors = ErrorReporterForTests() 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.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" 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") { test("test augmented expression asmgen") {
val src = """ val src = """
main { main {

View File

@ -541,10 +541,18 @@ class NumericLiteral(val type: DataType, // only numerical types allowed
return CastValue(true, NumericLiteral(targettype, number, position)) return CastValue(true, NumericLiteral(targettype, number, position))
} }
DataType.BYTE -> { DataType.BYTE -> {
if(targettype== DataType.UBYTE && number >= 0) if(targettype== DataType.UBYTE) {
return CastValue(true, NumericLiteral(targettype, number, position)) if(number in -128.0..0.0)
if(targettype== DataType.UWORD && number >= 0) return CastValue(true, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
return CastValue(true, NumericLiteral(targettype, number, 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) if(targettype== DataType.WORD)
return CastValue(true, NumericLiteral(targettype, number, position)) return CastValue(true, NumericLiteral(targettype, number, position))
if(targettype== DataType.FLOAT) if(targettype== DataType.FLOAT)
@ -563,10 +571,18 @@ class NumericLiteral(val type: DataType, // only numerical types allowed
DataType.WORD -> { DataType.WORD -> {
if(targettype== DataType.BYTE && number >= -128 && number <=127) if(targettype== DataType.BYTE && number >= -128 && number <=127)
return CastValue(true, NumericLiteral(targettype, number, position)) return CastValue(true, NumericLiteral(targettype, number, position))
if(targettype== DataType.UBYTE && number >= 0 && number <= 255) if(targettype== DataType.UBYTE) {
return CastValue(true, NumericLiteral(targettype, number, position)) if(number in -128.0..0.0)
if(targettype== DataType.UWORD && number >=0) return CastValue(true, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
return CastValue(true, NumericLiteral(targettype, number, 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) if(targettype== DataType.FLOAT)
return CastValue(true, NumericLiteral(targettype, number, position)) return CastValue(true, NumericLiteral(targettype, number, position))
} }

View File

@ -1,5 +1,5 @@
%import textio %import textio
%import test_stack ;%import test_stack
%zeropage basicsafe %zeropage basicsafe
@ -31,8 +31,16 @@ main {
sub start() { sub start() {
; mcCarthy() ; 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 value = 0
ubyte one = 1 ubyte one = 1
@ -93,7 +101,7 @@ main {
} }
txt.nl() txt.nl()
test_stack.test() ;test_stack.test()
; ; a "pixelshader": ; ; a "pixelshader":