[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
issue COMPILER-DIAGNOSTICS, version 7
- To: cl-compiler@sail.stanford.edu
- Subject: issue COMPILER-DIAGNOSTICS, version 7
- From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
- Date: Fri, 16 Dec 88 13:57:11 MST
Dan and I have been trading messages furiously on this issue for the
past few days, and we think we've finally come up with an acceptable
writeup. The major changes since version 4 are that the NOTICE
condition is now fully specified, and an example has been added.
There have also been some changes to the wording; namely, what used to
be referred to as an "error handler" is now referred to as a
"condition handler" to make it clear that it can intercept all kinds
of conditions, not just errors.
-Sandra
Issue: COMPILER-DIAGNOSTICS
References: CLtL p. 438-439, 62, 69, 160, 161
Condition System, Revision #18
S:>KMP>cl-conditions.text.34
Issue GC-MESSAGES
Issue RETURN-VALUES-UNSPECIFIED
Issue COMPILER-VERBOSITY
Category: CLARIFICATION, ENHANCEMENT
Edit History: V1, 15 Oct 1988, Sandra Loosemore
V2, 19 Oct 1988, Sandra Loosemore (minor fixes)
V3, 25 Oct 1988, Sandra Loosemore (input from Pitman & Gray)
V4, 01 Nov 1988, Sandra Loosemore (fix typos)
V5, 15 Dec 1988, Dan L. Pierson (new condition types)
V6, 15 Dec 1988, Sandra Loosemore (additions, fix wording)
V7, 16 Dec 1988, Dan L. Pierson (minor cleanup)
Problem Description:
It is unclear whether various diagnostics issued by the compiler are
supposed to be true errors and warnings, or merely messages.
In some implementations, COMPILE-FILE handles even serious error
situations (such as syntax errors) by printing a message and then
trying to recover and continue compiling the rest of the file, rather
than by signalling an error. While this user interface style is just
as acceptable as invoking the debugger, it means that a normal return
from COMPILE-FILE does not necessarily imply that the file was
successfully compiled.
Many compilers issue warnings about programming style issues (such as
binding a variable that is never used but not declared IGNORE).
Sometimes these messages obscure warnings about more serious problems,
and there should be some way to differentiate between the two. For
example, it should be possible to suppress the style warnings.
Also, neither CLtL nor issue RETURN-VALUES-UNSPECIFIED states what the
return value from COMPILE-FILE should be.
Proposal COMPILER-DIAGNOSTICS:USE-HANDLER:
(1) Add the following to the language:
NOTICE [Type]
The notice type is a subtype of CONDITION, disjoint from
WARNING, SEVERE-CONDITION, and SIMPLE-CONDITION. All types of
notices should inherit from this type.
SIMPLE-NOTICE [Type]
Conditions signalled by NOTICE when given a format string as a
first argument are of this type. This is a subtype of NOTICE,
and in implementations supporting multiple inheritance, this
type will also be a subtype of SIMPLE-CONDITION. The init
keywords :FORMAT-STRING and :FORMAT-ARGUMENTS are supported to
initialize the slots, which can be accessed using
SIMPLE-CONDITION-FORMAT-STRING and SIMPLE-CONDITION-FORMAT-ARGUMENTS.
ALERT [Type]
This is a subtype of NOTICE.
NOTICE datum &rest arguments [Function]
This function signals a condition of type NOTICE. The arguments
are interpreted similarly to those for the function WARN; if the
"datum" is a string, then a condition of type SIMPLE-NOTICE will
be signalled.
While the NOTICE is being signalled, this function establishes
the MUFFLE-NOTICE restart for use by a handler to cause the NOTICE
function to return immediately without further action. If no
handlers for the notice condition are found, or if all such
handlers decline, then the condition will be reported to
*ERROR-OUTPUT*.
The value returned by NOTICE is NIL.
MUFFLE-NOTICE [Function]
This function transfers control to the restart named MUFFLE-NOTICE.
If no such restart exists, MUFFLE-NOTICE signals an error of type
CONTROL-ERROR.
(2) Clarify that ERROR, WARNING, and ALERT conditions may be signalled
within COMPILE or COMPILE-FILE, including arbitrary errors which may
occur due to compile-time processing of (EVAL-WHEN (COMPILE) ...)
forms or macro expansion.
Considering only those conditions signalled -by- the compiler (as
opposed to -within- the compiler),
(a) Conditions of type ERROR may be signalled by the compiler in
situations where the compilation cannot proceed without
intervention.
Examples:
file open errors
syntax errors
(b) Conditions of type WARNING may be signalled by the compiler in
situations where the standard explicitly states that a warning must,
should, or may be signalled; and where the compiler can determine
that a situation that "is an error" would result at runtime.
Examples:
violation of type declarations
SETQ'ing or rebinding a constant defined with DEFCONSTANT
calls to built-in Lisp functions with wrong number of arguments
or malformed keyword argument lists
referencing a variable declared IGNORE
unrecognized declaration specifiers
(c) All other diagnostics issued by the compiler should be conditions
of type ALERT. In particular, this category includes all
diagnostics about matters of programming style. Although
conditions of type ALERT -may- be signalled in these
situations, no implementation is -required- to do so.
However, if an implementation does choose to signal a
condition, that condition will be of type ALERT and will be
signalled by a call to the function NOTICE.
Examples:
redefinition of function with different argument list
unreferenced local variables not declared IGNORE
declaration specifiers described in CLtL but ignored by
the compiler
(3) Require COMPILE-FILE to establish a condition handler. Add a
:HANDLER keyword argument to COMPILE-FILE, which is a user condition
handler function which is to be used during compilation. If the user
handler is not supplied or declines to handle a condition, then the
compiler's default handler will be invoked. Require the compiler
to handle the ABORT restart by aborting the smallest feasible part
of the compilation.
(4) Specify that COMPILE-FILE returns three values. The first value is the
truename of the output file, or NIL if the file could not be created.
The second value is non-NIL if errors were signalled during compilation
that were not handled by the user condition handler (indicating that
the output file is almost certainly unusable). The third value is
non-NIL if warnings were signalled during compilation that were not
handled by the user condition handler (indicating that the output
file may or may not be usable).
(5) Clarify that COMPILE does not establish a condition handler. Instead,
it uses whatever condition handler has been established in the environment
from which it is called.
Rationale:
Point by point,
(1) The new condition types NOTICE and ALERT are structured to allow
this part of the condition hierarchy to be further extended. In
particular, the issue COMPILER-VERBOSITY proposes an additional
subtype of NOTICE named INFO. The description of the NOTICE
function parallels the behavior of WARN.
(2) Conditions such as syntax errors which are errors in the interpreter
remain errors in the compiler. The division of other conditions
into WARNINGs and ALERTs allows potentially serious problems to be
distinguished from mere kibbitzing on the part of the compiler.
(3) It is reasonable for the default handling of compiler errors not to
cause the debugger to be invoked. However, any condition handler
established by COMPILE-FILE would override handlers established by the
user in the surrounding environment.
Requiring the compiler to handle the ABORT restart reflects what
several implementations already do (although probably not using this
mechanism). The intent of the wording is to allow an implementation
to abort the entire file compilation if it is not feasible to abort a
smaller part.
(4) This allows users to determine whether or not COMPILE-FILE is able to
actually compile the file successfully. Returning several values is
is more useful than a single success/failure value because there are
several degrees of failure.
(5) This is to reflect the use of COMPILE-FILE as being more "batch"-oriented
and COMPILE as being more interactive. There is less motivation to have
COMPILE try to recover from errors without user interaction.
Test Case/Example:
An example to illustrate how COMPILE-FILE should set up its condition
handlers is:
(defvar *output-file-truename* nil)
(defvar *errors-detected* nil)
(defvar *warnings-detected* nil)
;;; Call INTERNAL-COMPILE-FILE to do the real work. Note, that function
;;; may set up additional ABORT restarts.
(defun compile-file (input-file &key output-file handler)
(let ((*output-file-truename* nil)
(*errors-detected* nil)
(*warnings-detected* nil))
(with-simple-restart (abort "Abort compilation.")
(handler-bind ((condition #'compile-file-default-handler))
(if handler
(handler-bind ((condition handler))
(internal-compile-file input-file output-file))
(internal-compile-file input-file output-file))))
(values *output-file-truename*
*errors-detected*
*warnings-detected*)))
;;; The default condition handler keeps track of errors and warnings,
;;; and may also perform other implementation-specific actions.
(defun compile-file-default-handler (condition)
(typecase condition
(error
(setq *errors-detected* t)
...)
(warning
(setq *warnings-detected* t)
...)
(alert
...)
))
Current Practice:
No implementation behaves exactly as specified in this proposal.
In VaxLisp, COMPILE-FILE handles most compile-time errors without
invoking the debugger. (It gives up on that top-level form and moves on
to the next one.) Instead of signalling errors or warnings, it simply
prints them out as messages.
In Lucid Common Lisp, COMPILE-FILE invokes the debugger when it encounters
serious problems. COMPILE-FILE returns the pathname for the output file.
Symbolics Genera usually tries to keep compiling when it encounters errors;
so does Symbolics Cloe.
On the TI Explorer, the compiler tries to catch most errors and turn
them into warnings (except for errors on opening a file), but the user
can change special variable COMPILER:WARN-ON-ERRORS to NIL if he wants
to enter the debugger on an error signalled during reading, macro
expansion, or compile-time evaluation. The true name of the output
file is returned as the first value. A second value indicates whether
any errors or warnings were reported.
Cost to implementors:
The cost to implementors is not trivial but not particularly high. This
proposal tries to allow implementations considerable freedom in what
kinds of conditions the compiler must detect and how they are handled,
while still allowing users some reasonably portable ways to deal with
compile-time errors.
Cost to users:
This is a compatible extension. This proposal may cause users to see
some small differences in the user interface to the compiler, but
implementations already vary quite widely in their approaches. Some
users will probably have to make some minor changes to their code.
Adding the new functions and types may cause conflicts with user code
already using those names.
Benefits:
Users are given a way to detect and handle compilation errors, which
would simplify the implementation of portable code-maintenance
utilities. The behavior of the compiler in error situations is made
more uniform across implementations.
Discussion:
The issue of whether the compiler may print normal progress messages
is discussed in detail in a separate issue, COMPILER-VERBOSITY.
We contemplated making the NOTICE condition be a subtype of WARNING
instead of introducing a parallel set of types and functions. It was
thought that some possible uses of NOTICEs would not justify being
classified as warnings (although it would not be totally unreasonable
for the purposes of this proposal to classify ALERT under WARNING
instead of NOTICE). We also contemplated using the name MESSAGE
instead of NOTICE, but it was felt that NOTICE would be less likely to
cause conflicts with existing user code.
Pitman says that he would like to require COMPILE-FILE's default
condition handler never to invoke the debugger. I have left that out
of this proposal because it seems like an unnecessary restriction; if
users want to ensure that kind of behavior it is possible to do so by
supplying a user handler. (Of course, the converse is also true.)
Some of the things specified in section 2c as being ALERTS were
described in CLtL as being WARNINGs. There seems to be general
agreement that these things (particularly complaints about unused
variables) are not as serious as other problems described as warnings.
We might consider introducing a COMPILER-CONDITION that can be used in
mixins with the other condition types, so that error handlers can
distinguish between errors signalled by the compiler itself and errors
signalled during macroexpansion or EVAL-WHEN processing. This would
have to wait until the condition system is fully CLOSified.
Gray would like to exclude errors resulting from failure to open the
input and output files from the compiler's error handling. He also
suggests that the :HANDLER keyword argument be renamed :ERROR-HANDLER.
Some might wonder why NOTICE is needed instead of just making ALERT a
subtype of WARNING. This is for compatability with other proposed
conditions, notably INFO. While it might be reasonable to say that a
style "warning" is a legitimate WARNING error message, it is really
hard to justify WARNING status for a message like
;;; Starting to compile file foo.
Possibly NOTICE should write to *STANDARD-OUTPUT* rather than
*ERROR-OUTPUT*.
The initial names were MESSAGE and NOTICE, instead of NOTICE and
ALERT. They were changed in hopes of breaking fewer user function
definitions. Suggestions for better names are welcome.
-------