On Feb 25, 2007, at 11:19 AM, William D Clinger wrote:

Mike Sperber asked:
Why is it not enough for the compiler to just issue a warning, and to
then abort at run time?  (Scheme 48 also does some degree of arity
checking at compile time, and offers a special mode to make warnings
abort the compiler.)

According to the current draft R6RS, implementations
are not allowed to "abort at run time"; they would
have to raise a &violation exception, from which the
program might conceivably recover in a portable way.

I believe that's correct.  I also believe the rationale
for that is to allow people to write robust code without
performing their own error checking.  Example: I have a
file that contains a pair whose car I'm interested in.
I can open the file, read from it, and take the car of
that, all under one exception handler.  I assume you're
not proposing allowing implementations to abort at runtime
in this example, correct?

By legitimizing violations in that way, the draft
R6RS requires compilers to generate R6RS-compatible
code (whatever that means; see below) for programs
that violate the requirements of the draft.  That
means compilers must be written in such a way as
to continue to operate correctly when even the most
basic requirements of the R6RS are not met by the
program being compiled.

Here you talk about programs that violate the
requirements of the draft.  I am having a hard time
finding these requirements in the current draft.


That means compiler writers will have to write extra
code for the sole purpose of undoing optimizations
whose correctness temporarily assumes the program
being compiled contains no fundamental violations
of a kind that is easily detected after the program
has been transformed according to the optimization,
and is not so easily detected before the program
transformation.

I sympathize with that (as a compiler writer but not
as a user).  Let me give a simple example for the
readers who may not know the issue since they don't
deal with it directly.

It is well known that
(let ([lhs* rhs*] ...) body)
is equivalent to
((lambda (lhs* ...) body) rhs* ...)
My compiler expands the former to the latter during
macro expansion and transforms the latter to the former
in an early pass.  So, we can easily transform
((lambda (x) x) 12)  to  (let ([x 12]) x)

A small nuisance happens when the compiler attempts to
perform this optimization, only to discover that the
actual arguments do not match the formal arguments, and
therefore, the procedure call is invalid.  So, in these
circumstances, the compiler must be prepared to handle
such situation (cannot crash the compiler).  For a simple
example, ((lambda () 12) E) where E is an arbitrary
expression may be transformed to (other, more creative,
possibilities exist):

1. ((lambda () 12) E)   and detect the error at runtime.
2. (begin E (error ---))                   (my favorite)

So, what's being proposed is to permit implementors to
reject compiling some programs upon encountering such
situations instead of forcing the implementors to handle
this case in a more "graceful" way.

Requiring compiler writers to write
this extra code, instead of allowing them to reject
programs that violate the basic requirements of the
language, is a silly waste of implementors' time.

As I said, I sympathize, somewhat.  However, since I
actually fixed my compiler some time ago, I don't care
that much now (this may be due to Endowment Effect[*]).
Compare:

=== Native-code incremental compilers #1 & #2 ==================
> (call-with-current-continuation
    (lambda (k) ((lambda () 12) (k 17))))
17
>
=== Native-code incremental compiler #3 ========================
> (call-with-current-continuation
    (lambda (k) ((lambda () 12) (k 17))))
Error: Wrong number of arguments to known procedure (let () 12)
Entering debugger; type "?" for help.
debug>
================================================================

This is just one example to illustrate the point for the
non-implementors.

For some compiler writers, the most likely response
to a standard of silliness approaching that of the
current draft is to ignore the sillier parts of the
standard in their compilers, and to provide strict
R6RS conformance (whatever that means; see below)
only in their interpreters.  If at all.

No doubt :-)

Recognition of R6RS-compatible implementations might
go a long way toward convincing some compiler writers
that the R6RS language is worth implementing.

This statement is true (the higher the bar, the fewer
the conforming implementations).  Is it enough to permit
a low-bar R6RS-compatibility in the standard?  I don't
know.

Most
of those who would insist upon an R6RS-conforming
implementation would be happy using an interpreter.

Maybe.  But wouldn't you say that those same users may
be happier using an R6RS-conforming compiler?  I don't
see why you seem to imply that the two are mutually
exclusive.

Aziz,,,

[*] http://en.wikipedia.org/wiki/Endowment_effect


_______________________________________________
r6rs-discuss mailing list
[email protected]
http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss

Reply via email to