Richard A. O'Keefe
Fri Dec 12 00:30:09 CET 2003
test(A) -> a + 42. /* 1 */
I like to have tools that I can form mental models of.
Suppose we have a compiler that catches the clause above.
Now let's change it:
test(A) -> X = a, X + 42. /* 2 */
Now /* 2 */ _ought_ to have exactly the same semantics as /* 1 */.
But will it? Not if the compiler lets /* 2 */ past but rejects /* 1 */.
To be consistent, the compiler had better do some kind of data flow
analysis. But then we bring in
test(A) -> f(A) + 42. /* 3 */
f(A) -> a.
Apart from tracing, run time, and number of reductions, we'd expect
/* 3 */ to behave just like /* 1 */. Is it proposed that the compiler
will catch this also? Now we're into inter-procedural data flow analysis.
In order to predict which clauses will be rejected and which will be
allowed through, suddenly I have to know more than syntax rules and
variable scope, I have to know quite a bit about how the compiler works.
Now let's try another one. This one is NOT expected to have the same
semantics as /* 1 */, /* 2 */, or /* 3 */.
test(A) -> if 0==0 -> A+42 ; 1==0 -> a+42 end. /* 4 */
Why should the compiler warn about a+42 when there is no possibility of
that expression ever being evaluated?
In order to figure out whether /* 4 */ will be accepted or rejected,
I have to know whether the compiler does its weak type checking before
or after dead code elimination.
A compiler can warn about anything. There's nothing to stop a compiler
saying "Warning: your PC has a camera, you are UGLY." or even
"Warning: code compiled on Friday 13 may not work" or
"Warning: I've seen this before and I didn't like it then either".
But *inconsistent* rejection is another matter entirely.
Consider the following Haskell program as an analogue:
main = print (x `div` x)
x :: Int
x = 0
This is guaranteed to produce an error at run time. Guaranteed.
0 is not a legal right argument for `div`; this is just like the
fact that 'a' is not a legal argument for + .
I tried this program with three different Haskell compilers.
All of them were completely silent about it at compile time.
All of them gave a run time exception.
Yet some of them do quite serious unfolding; at least one of them
_must_ have noticed that I was asking for (0 `div` 0).
My vote would therefore be for option 2:
warn about it but still generate code.
More information about the erlang-questions