[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


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. 


References:	CLtL p. 438-439, 62, 69, 160, 161
	    Condition System, Revision #18
	    Issue GC-MESSAGES
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.


(1) Add the following to the language:

    NOTICE							[Type]
	The notice type is a subtype of CONDITION, disjoint from
        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

    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

	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

(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

	    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.

	    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.

	    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.


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*

    ;;; 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
	    (setq *errors-detected* t)
	    (setq *warnings-detected* t)

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.


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.


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

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.