lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




Le mer. 14 nov. 2018 à 21:55, Dibyendu Majumdar <mobile@majumdar.org.uk> a écrit :
On Wed, 14 Nov 2018 at 19:55, Egor Skriptunoff
<egor.skriptunoff@gmail.com> wrote:
>
>
> OK, let's test it!
>
> 1)
> A bug: correct Lua 5.3 program doesn't run on Ravi.
>    C:\Software\ravi\bin>ravi -e"for x = 1, 2 do x = 42.0 end"
>    ravi: (command line):1: Invalid assignment: integer expected near 'end'
>

In this case Ravi is deciding that x is an integer type and hence
doesn't like that you are assigning a floating point value.

That's because it attempts to optimize the integer loop unsafely: when compiling x=42.0, which changes the loop variable, it forgets to evaluate the loop condition (x<=42) which would normally imply that this assignment to x causes a break to the loop; but as this x variable is local to the loop and this assigned value is then not used after breaking, the assignment has no other effect than breaking the loop, so this code would be nearly like "for x = 1, 2 do break end" i.e. it will do nothing if compiled properly; if the code is interpreted, the for loop will be executed only once (local x=1 when entering the first loop which sets x=42.0, and exiting immediately which deletes the x variable).
There is code where modifying the loop control variable is perfectly valid, even if in general this is done by assigning a value of the same type.

A simple loop of the form "for x = a,b do... end" does not even require that "a" and "b" be the same type, it just needs that they are comparable ; the type assigned to "x" and incremented is the type of "a", not "b", the loop will compare "x <= b" after incrementing "x" which is the type of "a" (the type of the control variable "x" is not necessarily an "integer", actually in Lua it is just a "number");
the optimization to use integers has to be checked: you can optimize the compilation of "b" to an integer (if "a" is an integer) by compiling "for x = a,b do... end" as "for x = a,int(ceil(b)) do... end", then by compiling the inner assignment "x = 42.0" as "x=int(ceil(42.0)", i.e. "x=42".

But beware of the valid range of your optimized integers: Lua numbers have a wider range and allows a "for x=a,b" control variable to be any "number"; given the precision needed for incrementations to be working, the "a", and "b" numbers must be strictly between -2^53 and 2^53-1 (if "number" is compiled as an 64-bit IEEE "double precision floatting point") or between -2^24 and 2^24 (if "number" is compiled as an 32-bit IEEE "single precision floatting point"), otherwise the loop will be infinite. If your optimized code uses just a 32-bit integer, it may overflow when entering the loop or before reaching the end of the loop, or the end value "b" of the loop could be incorrectly truncated to be lower than "a" and the loop will never execute at all!

Writing  "for x = (a),(b) do (...) end" is only syntaxic sugar for: "do local x = (a); while x < (b) do (...); x = x + 1 end end"