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

compile-time actions & top-level forms (long)

The following is a rough proposal I've put together to try to get some
agreement on what the compile-time behavior of certain top-level
macros should be.  I came up with many items on this list by noting
things that were "broken" or behaved surprisingly in some
implementations; KCL is certainly the worst offender in this respect.
The situations I've listed appear to be fairly standard programming
practices and I think we need to state explicitly somewhere that CL
supports them. 

I have found that some implementations also have disturbing variations
from the behavior that is explicitly specified in CLtL regarding
evaluation of ordinary function calls appearing at the top level.
Some implementors have responded to my complaints by saying, in
effect, that if I don't like the default behavior they provide, I can
always explicitly wrap the offending form in an eval-when to get the
behavior I want.  This just isn't good enough -- if everybody is free
to diverge from CLtL however they want, then I'd have to wrap *every*
top-level form with an eval-when to guarantee portability.  Do we
really want to force that on unsuspecting users? 

In many of these cases, the top-level form needs to store information
at compile time.  I'm leaving open the possibility that the place where
the information is stored during compile-time processing might be 
different than where it gets stored during normal load/eval processing.
My primary concern is that the information be available for use by the
compiler later on during the compilation of the same file.

A simple implementation technique (one which I've used to patch KCL,
for example) is to simply wrap the forms which store the information
in the macro expansion with an (eval-when (eval compile load) ...).

As a separate but related issue, I'd also like to see a DEF<something>
form defined to replace the magical compile-time behavior of the
package functions. 

DEFTYPE.  Type names defined via DEFTYPE should be recognized as valid
in subsequent type declarations.

	(deftype small-int '(int 0 10))

	(let ((x 0))
	     (declare (type small-int x))

DEFMACRO.  Macro definitions must be stored at compile time, so that
occurences of the macro later on in the file will be expanded

	(defmacro silly (x) `(car ,x))

	... (silly foo) ....	; should compile as (car foo)

DEFUN.  Nothing special is required here, although an implementation may
wish to store information about the lambda-list (etc.) for the purposes
of compile-time error checking.

DEFVAR, DEFPARAMETER.  The compiler must recognize that the variables
have been proclaimed special.  It is probably not a good idea to evaluate
the initial-value form.

	(defvar *stack* (some-incredibly-hairy-function))

	(let ((*stack* *stack*))	; this should be a special binding.

DEFCONSTANT.  If this "normally" stores any information that is used by
the compiler (for example, to warn about assignment to or rebinding of
the variable), then this information should also be stored at compile time.
It's probably acceptable to evaluate the initial-value form in this case.

DEFSETF.  The SETF method should be available during the expansion of
calls to SETF later on in the file.  (Does anybody care about

	(defsetf foo modify-foo)

	(setf (foo x y) z)

DEFSTRUCT.  The structure type name must be recognized as a valid type
name in declarations (as in the DEFTYPE example above).  In addition,
further DEFSTRUCT definitions should be able to :include a structure
type defined earlier in the file being compiled.  The functions which
DEFSTRUCT generates may or may not be available at compile time.

	(defstruct person name age sex)
	(defstruct (astronaut (:include person) (:conc-name astro-))
	    (favorite-beverage 'tang))

Questions & comments are welcome....