changed float handling and appropriate compiler messages

This commit is contained in:
Irmen de Jong 2018-09-25 19:52:59 +02:00
parent d990b05998
commit 53cd50ad48
8 changed files with 42 additions and 45 deletions

View File

@ -25,11 +25,9 @@
flt(44)
for pixely in yoffset to yoffset+height-1 {
; yy = (pixely-yoffset)/height/3.6+0.4 ; @todo compiler float error
yy = flt((pixely-yoffset))/height/3.6+0.4
for pixelx in xoffset to xoffset+width-1 {
; xx = (pixelx-xoffset)/width/3+0.2 ; @todo compiler float error
xx = flt((pixelx-xoffset))/width/3+0.2
x = 0.0

View File

@ -4,41 +4,26 @@
sub start() -> () {
byte i=2
float f
word ww = $55aa
byte i
set_carry()
clear_carry()
set_irqd()
clear_irqd()
f=flt(i)
i = msb(ww)
i = lsb(ww)
lsl(i)
lsr(i)
rol(i)
ror(i)
rol2(i)
ror2(i)
float yy
word pixely
word yoffset
word height
while i<10 {
_vm_write_num(i)
_vm_write_char($8d)
i++
}
_vm_write_char($8d)
i=2
repeat {
_vm_write_num(i)
_vm_write_char($8d)
i++
} until i>10
; @todo expression must not result in float but in word
yy = flt(height+1.1)
pixely = height / 100
;yy = height- 1.1
;yy = height*1.1
;yy = height/3.6
;yy = height//3.6
;yy = height**3.6
;yy = height%3.6
;yy = height/3.6+0.4
;yy = 2/height/3.6+0.4
;yy = (pixely-yoffset)/height/3.6+0.4
}
}

View File

@ -725,8 +725,7 @@ class BinaryExpression(var left: IExpression, val operator: String, var right: I
val leftDt = left.resultingDatatype(namespace)
val rightDt = right.resultingDatatype(namespace)
return when(operator) {
"+", "-", "*", "**", "%" -> if(leftDt==null || rightDt==null) null else arithmeticOpDt(leftDt, rightDt)
"/" -> if(leftDt==null || rightDt==null) null else DataType.FLOAT
"+", "-", "*", "**", "/", "%" -> if(leftDt==null || rightDt==null) null else arithmeticOpDt(leftDt, rightDt)
"//" -> if(leftDt==null || rightDt==null) null else integerDivisionOpDt(leftDt, rightDt)
"&" -> leftDt
"|" -> leftDt

View File

@ -722,7 +722,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
if(sourceDatatype==DataType.WORD && targetDatatype==DataType.BYTE)
checkResult.add(ExpressionError("cannot assign word to byte, use msb() or lsb()?", position))
else if(sourceDatatype==DataType.FLOAT && (targetDatatype==DataType.BYTE || targetDatatype==DataType.WORD))
checkResult.add(ExpressionError("cannot assign ${sourceDatatype.toString().toLowerCase()} to ${targetDatatype.toString().toLowerCase()}; possible loss of precision", position))
checkResult.add(ExpressionError("cannot assign float to ${targetDatatype.toString().toLowerCase()}; possible loss of precision. Suggestion: round the value or revert to integer arithmetic", position))
else
checkResult.add(ExpressionError("cannot assign ${sourceDatatype.toString().toLowerCase()} to ${targetDatatype.toString().toLowerCase()}", position))

View File

@ -289,6 +289,15 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
stackvmProg.instr(Opcode.NOP)
}
private fun checkForFloatPrecisionProblem(left: IExpression, right: IExpression) {
val leftDt = left.resultingDatatype(namespace)
val rightDt = right.resultingDatatype(namespace)
if (leftDt == DataType.BYTE || leftDt == DataType.WORD) {
if(rightDt==DataType.FLOAT)
printWarning("byte or word value implicitly converted to float. Suggestion: use explicit flt() conversion or revert to integer arithmetic", left.position)
}
}
private fun translate(expr: IExpression) {
when(expr) {
is RegisterExpr -> {
@ -299,6 +308,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
translatePrefixOperator(expr.operator)
}
is BinaryExpression -> {
checkForFloatPrecisionProblem(expr.left, expr.right)
translate(expr.left)
translate(expr.right)
translateBinaryOperator(expr.operator)

View File

@ -7,7 +7,7 @@ import prog8.ast.Module
import prog8.parser.ParsingFailedError
/**
* TODO: array, matrix, string and float constants should be put into a constant-pool
* TODO: array, matrix, string and float constants should be put into a constant-pool,
* so that they're only stored once instead of replicated everywhere.
* Note that initial constant folding of them is fine: it's needed to be able to
* optimize the expressions. But as a final step, they should be consolidated again

View File

@ -1178,7 +1178,7 @@ class TestStackVmOpcodes {
@Test
fun testReturn() {
// @todo only tests return with zero return values
// @todo this only tests return with zero return values for now.
val ins = mutableListOf(
Instruction(Opcode.RETURN),
Instruction(Opcode.TERMINATE),
@ -1199,7 +1199,7 @@ class TestStackVmOpcodes {
@Test
fun testCall() {
// @todo only tests call with zero parameters
// @todo this only tests call with zero parameters for now.
val ins = mutableListOf(
Instruction(Opcode.CALL, callLabel = "label"),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "returned")),

View File

@ -372,7 +372,7 @@ for normal assignments (``A = A + X``).
The reverse is *not* true: it is *not* possible to assign a value of a 'larger' datatype to
a variable of a smaller datatype without an explicit conversion. Otherwise you'll get an error telling you
that there is a loss of precision. You can use builtin functions such as ``round`` and ``lsb`` to convert
to a smaller datatype.
to a smaller datatype, or revert to integer arithmetic.
Expressions
-----------
@ -385,13 +385,18 @@ There are various built-in functions such as sin(), cos(), min(), max() that can
You can also reference idendifiers defined elsewhere in your code.
.. attention::
**Data type conversion (during calculations):**
**Data type conversion (during calculations) and floating point handling:**
BYTE values used in arithmetic expressions (calculations) will be automatically converted into WORD values
if the calculation needs that to store the resulting value. Once a WORD value is used, all other results will be WORDs as well
(there's no automatic conversion of WORD into BYTE).
*There is never an automatic conversion into floating point values, and the compiler will NOT issue a warning for this.*
If you require float precision, you'll have to first convert into a floating point explicitly using the ``flt`` builtin function.
For example, this means that if you divide two integer values (say: ``32500 / 99``) the result will be the integer floor
When a floating point value is used in a calculation, the result will be a floating point, and byte or word values
will be automatically converted into floats in this case. The compiler will issue a warning though when this happens, because floating
point calculations are very slow and possibly unintended!
Calculations with integers will not result in floating point values;
if you divide two integer values (say: ``32500 / 99``) the result will be the integer floor
division (328) rather than the floating point result (328.2828282828283). If you need the full precision,
you'll have to write ``flt(32500) / 99`` (or if they're constants, simply ``32500.0 / 99``), to make sure the
first operand is a floating point value.