avoid silent type casts that remove precision (such as float -> word)

This commit is contained in:
Irmen de Jong 2020-08-20 12:49:48 +02:00
parent 65ba91411d
commit 774897260e
7 changed files with 27 additions and 23 deletions

View File

@ -277,7 +277,7 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(type)
override fun constValue(program: Program): NumericLiteralValue? {
val cv = expression.constValue(program) ?: return null
return cv.cast(type)
return cv.castNoCheck(type)
// val value = RuntimeValue(cv.type, cv.asNumericValue!!).cast(type)
// return LiteralValue.fromNumber(value.numericValue(), value.type, position).cast(type)
}
@ -398,7 +398,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
operator fun compareTo(other: NumericLiteralValue): Int = number.toDouble().compareTo(other.number.toDouble())
fun cast(targettype: DataType): NumericLiteralValue {
fun castNoCheck(targettype: DataType): NumericLiteralValue {
if(type==targettype)
return this
val numval = number.toDouble()
@ -567,7 +567,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
it
} else {
try {
num.cast(elementType)
num.castNoCheck(elementType)
} catch(x: ExpressionError) {
return null
}

View File

@ -1225,7 +1225,7 @@ internal class AstChecker(private val program: Program,
is AddressOf -> it.identifier.heapId(program.namespace)
is TypecastExpression -> {
val constVal = it.expression.constValue(program)
constVal?.cast(it.type)?.number?.toInt() ?: -9999999
constVal?.castNoCheck(it.type)?.number?.toInt() ?: -9999999
}
else -> -9999999
}

View File

@ -52,7 +52,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
assignment))
} else {
fun castLiteral(cvalue: NumericLiteralValue): List<IAstModification.ReplaceNode> =
listOf(IAstModification.ReplaceNode(cvalue, cvalue.cast(targettype), cvalue.parent))
listOf(IAstModification.ReplaceNode(cvalue, cvalue.castNoCheck(targettype), cvalue.parent))
val cvalue = assignment.value.constValue(program)
if(cvalue!=null) {
val number = cvalue.number.toDouble()
@ -109,14 +109,16 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
AddressOf(arg.second.value as IdentifierReference, arg.second.value.position),
call as Node)
} else if(arg.second.value is NumericLiteralValue) {
try {
val castedValue = (arg.second.value as NumericLiteralValue).cast(requiredType)
modifications += IAstModification.ReplaceNode(
call.args[arg.second.index],
castedValue,
call as Node)
} catch (x: ExpressionError) {
// no cast possible
if(argtype.isAssignableTo(requiredType)) {
try {
val castedValue = (arg.second.value as NumericLiteralValue).castNoCheck(requiredType)
modifications += IAstModification.ReplaceNode(
call.args[arg.second.index],
castedValue,
call as Node)
} catch (x: ExpressionError) {
// cast failed
}
}
}
}
@ -161,7 +163,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
// make sure the memory address is an uword
val dt = memread.addressExpression.inferType(program)
if(dt.isKnown && dt.typeOrElse(DataType.UWORD)!=DataType.UWORD) {
val typecast = (memread.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)
val typecast = (memread.addressExpression as? NumericLiteralValue)?.castNoCheck(DataType.UWORD)
?: TypecastExpression(memread.addressExpression, DataType.UWORD, true, memread.addressExpression.position)
return listOf(IAstModification.ReplaceNode(memread.addressExpression, typecast, memread))
}
@ -172,7 +174,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
// make sure the memory address is an uword
val dt = memwrite.addressExpression.inferType(program)
if(dt.isKnown && dt.typeOrElse(DataType.UWORD)!=DataType.UWORD) {
val typecast = (memwrite.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)
val typecast = (memwrite.addressExpression as? NumericLiteralValue)?.castNoCheck(DataType.UWORD)
?: TypecastExpression(memwrite.addressExpression, DataType.UWORD, true, memwrite.addressExpression.position)
return listOf(IAstModification.ReplaceNode(memwrite.addressExpression, typecast, memwrite))
}
@ -189,7 +191,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
if (returnValue.inferType(program).istype(subReturnType))
return noModifications
if (returnValue is NumericLiteralValue) {
returnStmt.value = returnValue.cast(subroutine.returntypes.single())
returnStmt.value = returnValue.castNoCheck(subroutine.returntypes.single())
} else {
return listOf(IAstModification.ReplaceNode(
returnValue,

View File

@ -34,7 +34,7 @@ internal class VariousCleanups: AstWalker() {
override fun before(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> {
if(typecast.expression is NumericLiteralValue) {
val value = (typecast.expression as NumericLiteralValue).cast(typecast.type)
val value = (typecast.expression as NumericLiteralValue).castNoCheck(typecast.type)
return listOf(IAstModification.ReplaceNode(typecast, value, parent))
}

View File

@ -171,7 +171,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
if(declValue!=null && decl.type==VarDeclType.VAR
&& declValue is NumericLiteralValue && !declValue.inferType(program).istype(decl.datatype)) {
// cast the numeric literal to the appropriate datatype of the variable
return listOf(IAstModification.ReplaceNode(decl.value!!, declValue.cast(decl.datatype), decl))
return listOf(IAstModification.ReplaceNode(decl.value!!, declValue.castNoCheck(decl.datatype), decl))
}
return noModifications
@ -323,13 +323,13 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke
val newFrom: NumericLiteralValue
val newTo: NumericLiteralValue
try {
newFrom = rangeFrom.cast(targetDt)
newTo = rangeTo.cast(targetDt)
newFrom = rangeFrom.castNoCheck(targetDt)
newTo = rangeTo.castNoCheck(targetDt)
} catch (x: ExpressionError) {
return range
}
val newStep: Expression = try {
stepLiteral?.cast(targetDt)?: range.step
stepLiteral?.castNoCheck(targetDt)?: range.step
} catch(ee: ExpressionError) {
range.step
}

View File

@ -29,7 +29,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
// try to statically convert a literal value into one of the desired type
val literal = typecast.expression as? NumericLiteralValue
if (literal != null) {
val newLiteral = literal.cast(typecast.type)
val newLiteral = literal.castNoCheck(typecast.type)
if (newLiteral !== literal)
mods += IAstModification.ReplaceNode(typecast.expression, newLiteral, typecast)
}

View File

@ -24,8 +24,10 @@ main {
uword xx = 4.5678
ubyte bb = 33
float ff = 1.234
foo2(-33)
foo(1.234, 4.456) ; TODO truncation warning
foo2(2.3456) ; TODO truncation warning
foo2(bb)
foo2(4.55) ; TODO truncation warning