mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 06:16:15 +00:00
Merge branch 'master' into structs
# Conflicts: # compiler/test/TestTypecasts.kt
This commit is contained in:
@@ -551,7 +551,6 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
else if(targetPointerDeref!=null) {
|
else if(targetPointerDeref!=null) {
|
||||||
TODO("assign to target pointer deref ${targetPointerDeref.position}.. not used anymore?")
|
|
||||||
val addressReg = codeGen.evaluatePointerAddressIntoReg(result, targetPointerDeref)
|
val addressReg = codeGen.evaluatePointerAddressIntoReg(result, targetPointerDeref)
|
||||||
val actualValueReg = if(targetPointerDeref.type.isFloat) valueFpRegister else valueRegister
|
val actualValueReg = if(targetPointerDeref.type.isFloat) valueFpRegister else valueRegister
|
||||||
codeGen.storeValueAtPointersLocation(result, addressReg, targetPointerDeref.type, zero, actualValueReg)
|
codeGen.storeValueAtPointersLocation(result, addressReg, targetPointerDeref.type, zero, actualValueReg)
|
||||||
|
|||||||
@@ -37,16 +37,16 @@ class TestNumericLiteral: FunSpec({
|
|||||||
sameValueAndType(NumericLiteral(BaseDataType.UWORD, 12345.0, dummyPos), NumericLiteral(BaseDataType.UWORD, 12345.0, dummyPos)) shouldBe true
|
sameValueAndType(NumericLiteral(BaseDataType.UWORD, 12345.0, dummyPos), NumericLiteral(BaseDataType.UWORD, 12345.0, dummyPos)) shouldBe true
|
||||||
}
|
}
|
||||||
|
|
||||||
test("test truncating") {
|
test("test truncating avoidance") {
|
||||||
shouldThrow<ExpressionError> {
|
shouldThrow<ExpressionError> {
|
||||||
NumericLiteral(BaseDataType.BYTE, -2.345, dummyPos)
|
NumericLiteral(BaseDataType.BYTE, -2.345, dummyPos)
|
||||||
}.message shouldContain "refused truncating"
|
}.message shouldContain "float value given for integer"
|
||||||
shouldThrow<ExpressionError> {
|
shouldThrow<ExpressionError> {
|
||||||
NumericLiteral(BaseDataType.BYTE, -2.6, dummyPos)
|
NumericLiteral(BaseDataType.BYTE, -2.6, dummyPos)
|
||||||
}.message shouldContain "refused truncating"
|
}.message shouldContain "float value given for integer"
|
||||||
shouldThrow<ExpressionError> {
|
shouldThrow<ExpressionError> {
|
||||||
NumericLiteral(BaseDataType.UWORD, 2222.345, dummyPos)
|
NumericLiteral(BaseDataType.UWORD, 2222.345, dummyPos)
|
||||||
}.message shouldContain "refused truncating"
|
}.message shouldContain "float value given for integer"
|
||||||
NumericLiteral(BaseDataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
|
NumericLiteral(BaseDataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
|
||||||
NumericLiteral(BaseDataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
|
NumericLiteral(BaseDataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
|
||||||
NumericLiteral(BaseDataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
|
NumericLiteral(BaseDataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ main {
|
|||||||
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
|
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
test("uword as pointer versus pointer to uword difference") {
|
xtest("uword as pointer versus pointer to uword difference") {
|
||||||
val src="""
|
val src="""
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|||||||
@@ -319,23 +319,21 @@ main {
|
|||||||
errors.errors[1] shouldContain "no cast"
|
errors.errors[1] shouldContain "no cast"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("refuse to truncate float literal 1") {
|
test("allow explicit float literal cast to integer") {
|
||||||
val text = """
|
val text = """
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
float @shared fl = 3.456 as uword
|
cx16.r0 = 1234.5678 as uword
|
||||||
fl = 1.234 as uword
|
cx16.r1L = 99.333 as ubyte
|
||||||
}
|
}
|
||||||
}"""
|
}"""
|
||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
compileText(C64Target(), false, text, outputDir, errors = errors) shouldBe null
|
compileText(C64Target(), false, text, outputDir, errors=errors) shouldNotBe null
|
||||||
errors.errors.size shouldBe 2
|
errors.errors.size shouldBe 0
|
||||||
errors.errors[0] shouldContain "refused"
|
|
||||||
errors.errors[1] shouldContain "refused"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("refuse to truncate float literal 2") {
|
test("refuse to truncate float inplace") {
|
||||||
val text = """
|
val text = """
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
main {
|
main {
|
||||||
@@ -351,23 +349,6 @@ main {
|
|||||||
errors.errors[0] shouldContain "in-place makes no sense"
|
errors.errors[0] shouldContain "in-place makes no sense"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("refuse to truncate float literal 3") {
|
|
||||||
val text = """
|
|
||||||
%option enable_floats
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
uword @shared ww = 3.456 as uword
|
|
||||||
ww++
|
|
||||||
ww = 3.456 as uword
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
val errors = ErrorReporterForTests()
|
|
||||||
compileText(C64Target(), false, text, outputDir, errors = errors) shouldBe null
|
|
||||||
errors.errors.size shouldBe 2
|
|
||||||
errors.errors[0] shouldContain "refused"
|
|
||||||
errors.errors[1] shouldContain "refused"
|
|
||||||
}
|
|
||||||
|
|
||||||
test("correct implicit casts of signed number comparison and logical expressions") {
|
test("correct implicit casts of signed number comparison and logical expressions") {
|
||||||
val text = """
|
val text = """
|
||||||
%import floats
|
%import floats
|
||||||
|
|||||||
@@ -621,30 +621,24 @@ class DirectMemoryRead(var addressExpression: Expression, override val position:
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NumericLiteral(val type: BaseDataType, // only numerical types allowed + bool (there is no separate BooleanLiteral node)
|
class NumericLiteral(val type: BaseDataType, // only numerical types allowed + bool (there is no separate BooleanLiteral node)
|
||||||
numbervalue: Double, // can be byte, word or float depending on the type
|
val number: Double, // can be byte, word or float depending on the type
|
||||||
override val position: Position) : Expression() {
|
override val position: Position) : Expression() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
val number: Double by lazy {
|
|
||||||
if(type==BaseDataType.FLOAT)
|
|
||||||
numbervalue
|
|
||||||
else {
|
|
||||||
val trunc = truncate(numbervalue)
|
|
||||||
if(trunc != numbervalue)
|
|
||||||
throw ExpressionError("refused truncating of float to avoid loss of precision", position)
|
|
||||||
trunc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
when(type) {
|
when(type) {
|
||||||
BaseDataType.UBYTE -> require(numbervalue in 0.0..255.0)
|
BaseDataType.UBYTE -> require(number in 0.0..255.0)
|
||||||
BaseDataType.BYTE -> require(numbervalue in -128.0..127.0)
|
BaseDataType.BYTE -> require(number in -128.0..127.0)
|
||||||
BaseDataType.UWORD -> require(numbervalue in 0.0..65535.0)
|
BaseDataType.UWORD -> require(number in 0.0..65535.0)
|
||||||
BaseDataType.WORD -> require(numbervalue in -32768.0..32767.0)
|
BaseDataType.WORD -> require(number in -32768.0..32767.0)
|
||||||
BaseDataType.LONG -> require(numbervalue in -2147483647.0..2147483647.0)
|
BaseDataType.LONG -> require(number in -2147483647.0..2147483647.0)
|
||||||
BaseDataType.BOOL -> require(numbervalue==0.0 || numbervalue==1.0)
|
BaseDataType.BOOL -> require(number==0.0 || number==1.0)
|
||||||
else -> require(type.isNumericOrBool) { "numeric literal type should be numeric or bool: $type" }
|
else -> require(type.isNumericOrBool) { "numeric literal type should be numeric or bool: $type" }
|
||||||
}
|
}
|
||||||
|
if(type!=BaseDataType.FLOAT) {
|
||||||
|
if(truncate(number) != number)
|
||||||
|
throw ExpressionError("float value given for integer datatype", position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isSimple = true
|
override val isSimple = true
|
||||||
@@ -863,16 +857,44 @@ class NumericLiteral(val type: BaseDataType, // only numerical types allowed
|
|||||||
}
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
try {
|
try {
|
||||||
if (targettype == BaseDataType.BYTE && number >= -128 && number <= 127)
|
when (targettype) {
|
||||||
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
BaseDataType.BYTE if number >= -128 && number <= 127 -> {
|
||||||
if (targettype == BaseDataType.UBYTE && number >= 0 && number <= 255)
|
val converted = number.toInt().toByte().toDouble()
|
||||||
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
if(implicit && converted!=number)
|
||||||
if (targettype == BaseDataType.WORD && number >= -32768 && number <= 32767)
|
return ValueAfterCast(false, "refused truncating of float to avoid loss of precision", this)
|
||||||
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
else
|
||||||
if (targettype == BaseDataType.UWORD && number >= 0 && number <= 65535)
|
return ValueAfterCast(true, null, NumericLiteral(targettype, converted, position))
|
||||||
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
}
|
||||||
if(targettype==BaseDataType.LONG && number >=0 && number <= 2147483647)
|
BaseDataType.UBYTE if number >= 0 && number <= 255 -> {
|
||||||
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
val converted = number.toInt().toUByte().toDouble()
|
||||||
|
if(implicit && converted!=number)
|
||||||
|
return ValueAfterCast(false, "refused truncating of float to avoid loss of precision", this)
|
||||||
|
else
|
||||||
|
return ValueAfterCast(true, null, NumericLiteral(targettype, converted, position))
|
||||||
|
}
|
||||||
|
BaseDataType.WORD if number >= -32768 && number <= 32767 -> {
|
||||||
|
val converted = number.toInt().toShort().toDouble()
|
||||||
|
if(implicit && converted!=number)
|
||||||
|
return ValueAfterCast(false, "refused truncating of float to avoid loss of precision", this)
|
||||||
|
else
|
||||||
|
return ValueAfterCast(true, null, NumericLiteral(targettype, converted, position))
|
||||||
|
}
|
||||||
|
BaseDataType.UWORD if number >= 0 && number <= 65535 -> {
|
||||||
|
val converted = number.toInt().toUShort().toDouble()
|
||||||
|
if(implicit && converted!=number)
|
||||||
|
return ValueAfterCast(false, "refused truncating of float to avoid loss of precision", this)
|
||||||
|
else
|
||||||
|
return ValueAfterCast(true, null, NumericLiteral(targettype, converted, position))
|
||||||
|
}
|
||||||
|
BaseDataType.LONG if number >=0 && number <= 2147483647 -> {
|
||||||
|
val converted = number.toInt().toDouble()
|
||||||
|
if(implicit && converted!=number)
|
||||||
|
return ValueAfterCast(false, "refused truncating of float to avoid loss of precision", this)
|
||||||
|
else
|
||||||
|
return ValueAfterCast(true, null, NumericLiteral(targettype, converted, position))
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
} catch (x: ExpressionError) {
|
} catch (x: ExpressionError) {
|
||||||
return ValueAfterCast(false, x.message,null)
|
return ValueAfterCast(false, x.message,null)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user