diff --git a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt index 699364c19..91424bea1 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -24,11 +24,16 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err try { val declConstValue = decl.value?.constValue(program) if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST) - && declConstValue.inferType(program) isnot decl.datatype) { - // 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)) + && declConstValue.type != decl.datatype) { + // avoid silent float roundings + if(decl.datatype in IntegerDatatypes && declConstValue.type==DataType.FLOAT) { + errors.err("refused silent rounding of float to avoid loss of precision", decl.value!!.position) + } 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) { errors.err(x.message, x.position) diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index af6818b1d..c02417ca5 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -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 override val position: Position) : Expression() { 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 fun copy() = NumericLiteralValue(type, number, position) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 12556f4cd..682e5f4c3 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -9,9 +9,6 @@ optimize TODO in "Add assignment to initialize with zero" in StatementReorderer optimize TODO in after(assignment) in VariousCleanups 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 - -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 if it knows about regular ram vs io space ram distinction. diff --git a/examples/test.p8 b/examples/test.p8 index 2ec107ce8..fddf9836f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,13 +5,12 @@ main { sub start() { - ubyte xx = 1.234 - ubyte yy = 2.234 + ubyte xx = 1 + ubyte yy = 2 uword aw byte bb float fl - ; TODO add these constant folders: ; (X + C1) + (Y + C2) => (X + Y) + (C1 + C2)