|
On Fri, Feb 12, 2021 at 6:59 PM Lux Lang <luxlisp@gmail.com> wrote:
>
> Hello, everyone.
>
> I have found a bug in Lua 5.4.2.
>
> The value of math.mininteger is the integer -9223372036854775808.
> If you were to write the number itself, instead of accessing it through the math.mininteger constant, the Lua parser would instead produce the float -9.2233720368548e+18
>
> This occurs both on the REPL, as well as when loading a Lua file.
>
> Funny enough the value just next to math.mininteger, which is to say -9223372036854775807, correctly parses into an integer instead of a float. So it seems only math.mininteger suffers this bug. The value of math.maxinteger also correctly parses into an integer.
>
> I can work around this bug, but I hope it's chosen to be fixed.
This is a caused by the fact that the lexer, as is the case in many
other languages, does not actually recognize negative numbers. So
-9223372036854775808 is not lexed as a single token, but as two
tokens: a minus operator followed by a *positive* integer. The parser
and compiler then turn that token sequence into a load of the positive
number followed by a unary minus operation.
The catch is that in a two's complement representation (used by
virtually every modern architecture out there these days), the
absolute value of the most negative number that can be represented by
a given number of bits is always one greater than the largest positive
integer that can be represented by the same number of bits. So
9223372036854775807 fits in a 64-bit signed integer, but
9223372036854775808 does not, even though -9223372036854775808 does.
Since 9223372036854775808 is too large to be represented as a 64-bit
signed integer, Lua coerces it to a float (technically, a
double-precision floating point number) at parse time.
When you access math.mininteger, Lua actually uses a system C header
macro to give you the proper minimum integer as defined by your system
C library, which is guaranteed to parse correctly in C code and
therefore be correctly represented in the memory bits.
Your second email about 0x8000000000000000 parsing correctly is
because there is no unary minus operation involved. Lua always parses
hexadecimal constants always as a positive integer, overflowing if
necessary. So 0x8000000000000000 parses as positive
9223372036854775808, which overflows to -9223372036854775808.