The current implementation considers a Value to be a GML real if the top 12 bits are not all-ones. This excludes negative infinity, which has a sign of 1, an exponent of all-ones, and a mantissa of all-zero, which currently gets treated as a GML string instead, converting negative infinity to a Symbol with index 0, or "true".
One solution is to make Symbols non-zero and additionally check for a zero mantissa, but that's more expensive- looking at the bottom 63 bits, it interleaves GML reals (0x0000_0... through 0x7ff0_0..., and 0x7ff8_0...) with tagged values (0x7ff0_0...1 through 0x7ff7_f..., and 0x7ff8_0...1 through0x7fff_f...`).
LuaJIT has a nicer solution, which moves the tagged value bit patterns up to the top of the space so the comparison can be a single < or <=. However, this eats one of their payload bits, because tags must start with 1 to remain above the canonical NaN (LuaJIT/LuaJIT#49) and this causes problems on ARM64, where Linux's default memory map includes user-space addresses with the 48th bit set.
I can see a few options to resolve this:
Mitigate the expense of the interleaved bit patterns by treating NaN as a tagged value, folding the check into the same match. Classic GML doesn't ever seem to handle NaNs (or even infinities) anyway.
Go with LuaJIT's approach, but drop down to 3 tag bits. This is more than enough for vanilla GML, though it may make some future extensions more of a pain. It also means GML strings no longer need to be non-zero.
A hybrid of the two- move the tags up (by 1 or all the way, either would work) to separate strings from infinities without forcing them to be non-zero, and keep the interleaving.
The current implementation considers a
Value
to be a GML real if the top 12 bits are not all-ones. This excludes negative infinity, which has a sign of 1, an exponent of all-ones, and a mantissa of all-zero, which currently gets treated as a GML string instead, converting negative infinity to aSymbol
with index 0, or"true"
.One solution is to make
Symbol
s non-zero and additionally check for a zero mantissa, but that's more expensive- looking at the bottom 63 bits, it interleaves GML reals (0x0000_0...
through0x7ff0_0...
, and0x7ff8_0...
) with tagged values (0x7ff0_0...1
through0x7ff7_f...
, and0x7ff8_0...1 through
0x7fff_f...`).LuaJIT has a nicer solution, which moves the tagged value bit patterns up to the top of the space so the comparison can be a single
<
or<=
. However, this eats one of their payload bits, because tags must start with 1 to remain above the canonical NaN (LuaJIT/LuaJIT#49) and this causes problems on ARM64, where Linux's default memory map includes user-space addresses with the 48th bit set.I can see a few options to resolve this:
match
. Classic GML doesn't ever seem to handle NaNs (or even infinities) anyway.