I think it might help to focus the discussion about remote environments
and meta object programming if we had a clearer picture of what the
goals are. The basic question is what kinds of things can be defined and
then used during compilation of the same file that defines them, and
what restrictions might apply.
DEFCLASS
* Can the class be used as a superclass of a later DEFCLASS? [clearly yes]
* Can it be used as a specializer in a DEFMETHOD? [clearly yes]
* Can a MAKE-INSTANCE be done by a macro expander, DEFCONSTANT, or "#."?
- If so, do initforms have access to macros and constants defined
earlier in the file?
* Can the class be used as the :METACLASS option of a later DEFCLASS?
- Can that second class be instantiated?
* Can it be used as the :GENERIC-FUNCTION-CLASS option of a
DEFGENERIC, GENERIC-FUNCTION, GENERIC-FLET, or GENERIC-LABELS?
* Can it be used as the :METHOD-CLASS option of a DEFGENERIC etc.?
- Can DEFMETHODs then be done for that generic function?
DEFGENERIC
* Referenced by later DEFMETHOD? [clearly yes]
* Is the function defined such that it can be called at compile time?
DEFMETHOD
* Can it be invoked at compile-time?
* In particular, will methods added to standard generic functions be
invoked by the system at compile time?
DEFINE-METHOD-COMBINATION
* Used in a later DEFGENERIC?
- Callable at compile-time?
Are there other interactions that need to be considered?
I think that the standard could take a simple, minimal, approach that
would still satisfy the most common usages. Suppose we said:
DEFCLASS
If it appears at top-level, then the class name is defined for use as
a type specifier or method specializer. It can also be used as a
superclass of a later DEFCLASS since they don't have to be defined
before being referenced anyway. The class object can be obtained by
calling FIND-CLASS with an environment argument, but it can only be
used in ways that do not require the class to be finalized. For
example, one could ask for its CLASS-DIRECT-SUPERCLASSES, but not its
CLASS-PRECEDENCE-LIST. Other uses, which could involve the need to
instantiate the class, could not be portably done in the same file
without wrapping an (EVAL-WHEN (EVAL COMPILE LOAD) ...) around the
DEFCLASS. Implementations would be free to support compile-time
instantiation as an extension. One way to look at this would be to
say that it is implementation-dependent whether FINALIZE-INHERITANCE
works or signals an error when given a class defined in the
compile-time environment.
DEFGENERIC
The attributes of the generic function that affect DEFMETHOD will be
recorded for use by definitions of methods for that generic function
later in the file. This includes the lambda-list and method class.
It is implementation-dependent whether this is actually put in the
form of a generic function object and whether other operations on that
generic function are possible at compile-time.
DEFMETHOD
Method definitions are not required to have any compile-time
side-effects, but the compiler may warn about things like undefined
specializer classes or non-congruent lambda-lists. ADD-METHOD is not
invoked at compile-time unless forced by using EVAL-WHEN.
DEFINE-METHOD-COMBINATION
No compile-time side-effect is required. The new combination can
still be referenced in DEFGENERICs and DEFMETHODs later in the file
since the definition is not really needed until the generic function
is called and an effective method needs to be computed. A compiler
could, however, notice what combination names have been defined and
issue a warning on a DEFGENERIC with an undefined combination
or a DEFMETHOD using an undefined qualifier.