give an error when initializing an integer var with a float value instead of silently rounding

This commit is contained in:
Irmen de Jong 2021-11-18 01:56:11 +01:00
parent fa11a6e18b
commit 8f379e2262
4 changed files with 22 additions and 12 deletions

View File

@ -24,11 +24,16 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err
try { try {
val declConstValue = decl.value?.constValue(program) val declConstValue = decl.value?.constValue(program)
if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST) if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST)
&& declConstValue.inferType(program) isnot decl.datatype) { && declConstValue.type != decl.datatype) {
// cast the numeric literal to the appropriate datatype of the variable // avoid silent float roundings
val cast = declConstValue.cast(decl.datatype) if(decl.datatype in IntegerDatatypes && declConstValue.type==DataType.FLOAT) {
if(cast.isValid) errors.err("refused silent rounding of float to avoid loss of precision", decl.value!!.position)
return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl)) } else {
// cast the numeric literal to the appropriate datatype of the variable
val cast = declConstValue.cast(decl.datatype)
if (cast.isValid)
return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl))
}
} }
} catch (x: UndefinedSymbolError) { } catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position) errors.err(x.message, x.position)

View File

@ -388,7 +388,16 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
numbervalue: Double, // can be byte, word or float depending on the type numbervalue: 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 = if(type==DataType.FLOAT) numbervalue else round(numbervalue) val number: Double by lazy {
if(type==DataType.FLOAT)
numbervalue
else {
val rounded = round(numbervalue)
if(rounded != numbervalue)
throw ExpressionError("refused silent rounding of float to avoid loss of precision", position)
rounded
}
}
override val isSimple = true override val isSimple = true
override fun copy() = NumericLiteralValue(type, number, position) override fun copy() = NumericLiteralValue(type, number, position)

View File

@ -9,9 +9,6 @@ optimize TODO in "Add assignment to initialize with zero" in StatementReorderer
optimize TODO in after(assignment) in VariousCleanups optimize TODO in after(assignment) in VariousCleanups
optimize: bitwise operations with a negative constant number -> replace the number by its positive 2 complement optimize: bitwise operations with a negative constant number -> replace the number by its positive 2 complement
optimize: add some more constant folders mentioned in test.p8 optimize: add some more constant folders mentioned in test.p8
fix: give error when initializing an integer var with a float value
optimize: there is an optimizations in AsmOptimizer that can only be done correctly optimize: there is an optimizations in AsmOptimizer that can only be done correctly
if it knows about regular ram vs io space ram distinction. if it knows about regular ram vs io space ram distinction.

View File

@ -5,13 +5,12 @@ main {
sub start() { sub start() {
ubyte xx = 1.234 ubyte xx = 1
ubyte yy = 2.234 ubyte yy = 2
uword aw uword aw
byte bb byte bb
float fl float fl
; TODO add these constant folders: ; TODO add these constant folders:
; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2) ; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2)