Closed MinusKelvin closed 6 years ago
For <=
and >=
, in clox, they are compiled as !(a > b)
and !(a < b)
which is equivalent for integers but not for floats (because of all the special values like nan). So the result of nan <= nan
is compiled as !(nan > nan)
which is true. In jlox, the interpret use the operators directly so there is no problem.
So, there are a couple of things going on here:
Double.equals()
in Java does not honor IEEE 754. Double.NaN == Double.NaN
evaluates to false, but Double.NaN.equals(Double.NaN)
evaluates to true. jlox uses the latter.
With NaN-tagging enabled, clox just does a straight bit comparison of the two values. Since NaNs have the same bit representation, that returns true.
Like @jube notes, >=
and <=
desugar to negating <
and >
.
I could fix 1 by special-casing doubles, but it's annoying. Same for 2. I'd prefer to not change 3 because (1) I already wrote that chapter and, (2) I think it's worth showing desugaring as a technique.
So my current inclination is to just add an aside noting that Lox doesn't fully do the right thing for NaNs and use it as an excuse to talk about how subtle compatibility issues can be. What do you think?
I think that's perfectly fine as people interested in IEEE compliance will know how to modify the c interpreter and others won't care.
The aside is a good idea, especially since language design can have a lot of corner cases most people don't think about that subtly break things (such as upcasting an Integer
to a String
with Java generics) and it would be good to draw attention to that.
jlox and clox have different behavior when working with not a number values. This code:
has this output in jlox:
and this output in clox:
Furthermore, the fact that
NaN == NaN
is true is surprising, as the IEEE standard definesNaN == NaN
to be false.