perm filename NEWMOP.TEX[CLS,LSP] blob sn#854508 filedate 1988-03-08 generic text, type T, neo UTF8
% -*- Mode: TeX -*-
\input macros
\drafttrue
\def\bookline{\CLOS\  Specification}
\def\chapline{Metaobject Protocol}

\beginChapter 3.{Common Lisp Object System Specification}%
{Metaobject Protocol}{Metaobject Protocol}

This document was written by Daniel G. Bobrow, Linda G. DeMichiel,\break
Richard P. Gabriel, Sonya E. Keene, Gregor Kiczales, and David A. Moon.

Contributors to this document include Patrick Dussud, Kenneth Kahn,\break
Jim Kempf, Larry Masinter, Mark Stefik,
Daniel L. Weinreb, and Jon L White.

\endTitlePage

\beginSection{Terminology}

For almost all the generic functions described below, there is only one
method defined in CLOS.  The specializers for
these methods are usually one or more of standard-class,
standard-method, standard-generic-function, and standard-object.  In the
case where there is only one method specified by the CLOS kernel, we use
the term "standard method" to refer to this method.  In the section
listing all the generic functions, we actually provide the full
signature for the methods.

\endSection%{Terminology}


\beginSection{Introduction}

The Common Lisp Object System can be described at three levels.
These levels are a set of mutually supporting facilities for use at
different levels of sophistication.  The first level, 
the programmer's interface, provides a
convenient syntax for defining classes and methods, which is all most
users need to know to construct object oriented programs in Common
Lisp.  The second level consists of the description of the functions
that underlie the basic facilities.  At this level, there is a complete
separation of objects and names, with all basic operations applicable
to strictly anonymous objects.  This level is useful for programmers
who wish to provide an alternative interface to the facilities or who
are building program development environments.    

The third level, the \CLOS\ kernel (CLOS kernel), 
describes CLOS as an object oriented program.   The \CLOS\
kernel comprises those classes, methods and generic functions which
implement the \CLOS\ system described in chapters 1 and 2.
The kernel classes define the data structures used, and the generic
functions and methods define the basic operations of the kernel,
as specialized to those kernel classes. We
liken this level of description to the description of Lisp or Scheme
using a metacircular interpreter written in the language. To
understand the behavior requires understanding the language.  The
metacircular interpreter thus provides a kind of intellectual bootstrap.
Because these generic functions, classes and instances comprise
the metacircular interpreter, we refer to them collectively as the
metaobjects of CLOS.  The {\it metaobject protocol} refers to
the operations (generic function with methods) defined on these
metaobjects.  A protocol is a set of related generic functions
for some purpose.

The CLOS kernel allows for detailed control and extensions to
the object system.  In Lisp, this type of control is usually achieved by
building an interpreter that tests many conditions explicitly, and
providing the users with ways of manipulating the conditions.  In this
distributed, object oriented interpreter, the standard behavior is
supported through methods specialized to the standard objects in the
system.  Specialization of the behavior of the interpreter is achieved
by defining classes that are subclasses of those provided by \CLOS\ ,
and specializing some of the generic functions described.   By defining
methods on the generic function specialized on these new subclasses,
programmers can build extensions or alternatives to the basic CLOS
framework.  This requires programming only the few methods that
implement the difference in behavior -- a standard way of extending an
object-oriented program.  The remaining functionality is shared. 

The CLOS kernel makes accessible the ``real'' CLOS interpreter as an
object oriented program written in CLOS. By ``real'' we mean two
things. First, the interpreter we describe is the one that is running;
that is, changes and extensions made to the generic functions described
will effect the operations of the system. Secondly, a ``real''
interpreter includes not only the direct operations of the language,
but provides access to mechanisms to control and support compile and
run time optimizations usually hidden from users.   

This chapter is organized as follows:

We start with a detailed description of the classes that are provided
with the CLOS system. After describing the inheritance relationships
of the classes, we describe the information contained in each class
by describing how to create instances of these classes.  We summarize 
from Chapter 1 how instances of standard-class are made using make-instance.
We then specify several generic functions mentioned there but not described
in chapter 2.  The critical specification for creation is the set of
arguments for the initialize-instance method for each class.  We describe 
these arguments for each of the objects that support
the standard facilities of CLOS.  The specification consists primarily
of the description of the arguments for methods of that generic function.
We further specify a set of "reader" methods that read information from
instances of the class stored by the initialize-instance method. This use
of the term reader is a pun on the the use of that term
as an automatically generated method for a class.  The similarity is that
each of these readers takes a class as its single argument and returns a
value relevant for that class..
 
We then describe a general reinitialization protocol for CLOS.  This
reinitialization protocol uses initialize-instance to update
instances, and also invokes a mechanism for updating other objects
that are dependent on the state of the reinitialized instance.
For each kernel class in CLOS, we specify when its instances can be
reinitialized, and how objects dependent on state of these instances
will be updated.

None of the operations above make any use of names for objects. The
user interface macros (defclass, defmethod, defgeneric) do use names.
We show how each of these macros expand, and describe the behavior of
the functions they expand into.

We then describe the instance structure protocol.  This consists of
two levels.  The slot level description involves the metaclass in the allocation of an instance, and the extraction of values for slots from the instance.  The access-key level of description provides users a mechanism for specifying storage to be allocated in instances in addition to slots, and a mechanism to access to that information.

The protocol for building generic functions is then described. 
It includes the generic function for computing the effective method for
a set of methods, and a generic function that can be specialized to
compute the code used by the generic function to do its discrimination.

Method combination objects are used in the computation of effective
methods.  We include a description of the
protocols used to create and manipulate these objects. 

Finally there is a description of some of the generic functions related to
make-instance but not previously described.


\endSection%{Introduction}


\beginSection{The Classes in the CLOS Kernel}

The specification of the class structure of the CLOS kernel is based on
a number of principles:

1) We specify only subclass relationships, and no direct subclasses. 
This allows implementations to insert implementation dependent classes
into the lattice, for example, to organize code sharing.
  
2) We specify as disjoint the metaclasses that support built-in classes,
structure classes and standard classes.  These metaclasses are 
{\it built-in-class}, {\it structure-class}, and {\it standard-class}
respectively.  This allows use of a simple
type test to determine the metaclass used by any class. 

3) We provide classes in the kernel to support default behavior of
instances of standard-class and structure-class.  These are the
classes {\it standard-object} and {\it structure-object} respectively.    

4) In the kernel, we define classes {\it class}, {\it slot-description},
{\it method}, {\it generic-function}, and {\it method-combination}.  These
classes are intended to act as superclasses for any implementations of
these types.  They contain no structure or behavior themselves.  These
are distinguished from the classes that support the behavior of the
user interface macros. The latter classes, subclasses of those above,
are {\it standard-class}, {\it standard-slot-description},
{\it standard-method}, {\it standard-generic-function}, and
{\it standard-method-combination}.   


5) We do not specify slots in any class in the kernel, although
implementations are free to use them.  We define reader generic
functions to obtain information from instances of a class.  Other
generic functions in the kernel are said to update this information,
without specifying how the updating is done. This allows
implementations to store information in compact forms not accessible by
the user.  It also allows an implementation to create and maintain
caches.

In the specification, we specify some readers as {\it storage readers}. By
this we mean they act as though they were reading slot values; that is,
they return the same value each time, unless a specific updating action
is done. We use the phrase {\it X is stored as a value for reader-Y} to
talk about the only way of changing the value associated with a storage
reader.  For example, class-direct-slots is a reader for
standard-class.  We say {\it the list of slot-description objects is stored
as the value for class-direct-slots.}  This circumlocution is necessary
because we want to limit places where updating is done, and we don't
want to define setf functions that are accessible to users. 



\beginSubSection{Lattice of Kernel Classes}

The following should be a real diagram, but for now we use indentation
to indicate subclass relationships.  We use angle brackets to indicate
those classes whose primary use is for type determination.  All of the
classes below are instances of standard-class except T, which is an
instance of built-in-class, and standard-generic-function, which is an
instance of funcallable-standard-class.

\vfill\eject

\screen!

T 
  <standard-structure>
  <standard-object>
    <generic-function>
        standard-generic-function 
    <method>
        standard-method 
        standard-accessor-method
            standard-reader-method
            standard-writer-method
    <method-combination>
        standard-method-combination
        simple-method-combination
    <slot-description>
        standard-slot-description
    <class>
        built-in-class
        structure-class
        standard-class
            funcallable-standard-class

\endscreen!

One subclass relationship is not shown; {\it generic-function} is also a
subclass of {\it function}. {\it function} is more specific than
{\it standard-object} in the class precedence list of 
{\it generic-function}.  {\it generic-function}
is the one class in the kernel that has multiple superclasses.
Implementation of this relationship awaits the change in Common Lisp
that makes function be a real type.

\endSubSection%{Lattice of Kernel Classes}

\beginSubSection{Instances of class, built-in-class and structure-class}

Instances of built-in-class are specified by the implementation, 
and have special constructors for their creation.  They may include
all the classes associated with Common Lisp types, though implementations
are free to use standard-classes for any of them. If make-instance is
called on an instance of built-in-class, an error is signalled.

CLOS does not specify the behavior of {\it structure-class} 
for make-instance. 



\endSubSection%{Instances of class, built-in-class and structure-class}

\beginSubSection{Instances of standard-class}

Instances of standard-class can be created using the make-instance
protocol described in chapters 1 and 2.  As shown in chapter 1, the
standard method for make-instance acts as though it were
defined as follows:

\screen!

(defmethod make-instance ((class standard-class) &rest initargs)
  (setq initargs (default-initargs class initargs))
  (check-initargs class initargs)
  (let ((instance (apply #'allocate-instance class initargs)))
    (apply #'initialize-instance instance initargs)
      instance))

\endscreen!

At this point we will describe the generic functions allocate-instance,
check-initargs and default-initargs.  The generic function
initialize-instance is described in chapter 2.  We will then describe
each of the classes in the kernel in terms of the arguments they
expect for initialize-instance, and the readers that can extract
information from instances of these classes.

\beginsubsubsection{allocate-instance}

\Defmeth {allocate-instance} {(class standard-class) \&rest initargs}

Allocate-instance for standard-class creates a structure that
has enough room to store information specified by the class.
It calls allocate-standard-instance to achieve this.  The underlying
mechanism for specifying how much storage is allocated, and how it
is accessed is described in the section on Instance Structure protocol.   

Particular implementations are free to add keyword arguments for
their own purposes (e.g. area allocation)

\endsubsubsection%{allocate-instance}

\beginsubsubsection{check-initargs}

\Defmeth {check-initargs} {(class standard-class) initargs}

The purpose of check-initargs is to determine if the keyword arguments
provided to make-instance are acceptable to either
initialize-instance or allocate-instance. 
It is equivalent to testing whether all the keyword arguments
in initargs are members of the list returned by 
{\bf (class-all-initargs class)}, but the latter need not be called by 
check-initargs each time.

\endsubsubsection%{check-initargs}

\beginsubsubsection{default-initargs}

\Defmeth {default-initargs} {(class standard-class) initarg-list}

The system-supplied method for {\bf default-initargs} implements the
{\bf :default-initargs} class option by appending initialization arguments
that do not appear in the {\it initarg-list\/} argument to the
{\it initarg-list\/} argument and returning the result.

The order of the initialization arguments appended to the list is
determined by the rules for duplicate initialization
arguments presented in the
section ``Rules for Duplicate Initialization Arguments.''

The {\it initarg-list\/} argument is not modified.


The result is an initialization argument list.  The results are undefined
if the value returned by this function is modified.


\endsubsubsection%{default-initargs}


\beginsubsubsection{Initializing standard-class}

In building instances of standard-class, the only method that is
specialized is initialize-instance.  The purpose of this method
is to check and normalize the input arguments, and to store appropriate
information in the class.

\Defmetha {initialize-instance} {(class standard-class)
    \&key :direct-superclasses :direct-slots :direct-options :documentation}

Arguments:

{\it direct-superclasses}

The direct-superclasses argument, if provided, must be a list of class
objects. The value of direct-superclasses is defaulted by
a call to

   (class-default-direct-superclasses class direct-superclasses).

The value returned from this call should be a list of class
objects to be used as a superclass for this class.

For each superclass in the returned-value, a call is made to

(valid-superclass-p class superclass) 

to check if the metaclass of the provided superclass is compatible
with the metaclass of class.  If valid-superclass-p returns nil,
an error is signalled. If there is no error for any class on the list,
the value is stored as the value for class-direct-superclasses.

For each class object on that list, add-direct-subclass is
called to maintain a backlink from super to subclasses.  This
is done before the value is stored.

If initialize-instance is not given a value for direct-superclasses,
then no value is stored.  If no value has ever been stored for 
class-direct-superclasses, then the class is considered not-initialized;
that is, class-initialized-p will return nil for this class.  Once a value
has been stored for class-direct-superclasses, then
class-initialized-p will return t.


{\bf direct-slots} The direct-slots argument, if given, must be a list of
slot-description objects.

For each element of this list,

(valid-slot-description-p class slot)

is used to check the compatibility of each slot-description-object.  If
valid-slot-description-p returns nil, an error is signalled 
  
This list is stored as the value of class-direct-slots.  
If initialize-instance is not given a value for direct-slots, and 
no value is currently stored for class-direct-slots, then nil is stored.

{\bf direct-class-options} This is a list of class options.
Each option must be a list.  Each option in the list is checked using

(valid-class-option-p class option)

If valid-class-option-p returns nil, an error is signalled.
If there are no errors, the argument direct-class-options is stored
as the value of class-direct-class-options.
If initialize-instance is not given a value for direct-options, and 
no value is currently stored for class-direct-options, then nil is stored. 

If class-options contains a :metaclass option, it must
pass the valid-class-option-p check.  It is left in the list of options,
but is ignored in further processing.  Processing of :metaclass is handled by
defclass expansion, or by using the specified class for make-instance.

{\bf :documentation}
This is a string used to document this standard-class.  It will be
accessible by the generic-function {\bf documentation}.  If no value 
is provided, and none has ever been provided, the empty string is stored.


\endsubsubsection%{Initializing standard-class}

\beginsubsubsection{class-default-direct-superclasses}

This generic function is called to determine the direct-superclasses
for a class.  It is called by the method for initialize-instance for
standard-class when direct-super-classes have been supplied. It
receives as arguments the class for which the superclasses are
intended, and the supplied superclasses. It returns a list of classes.

\Defmeth {class-default-direct-superclasses} {(class standard-class) supplied-superclasses}

The purpose of this method is to ensure that the class named standard-object
will be in the class precedence list of all standard-classes.  If
{\bf supplied-superclasses} is {\bf nil}, this method returns
a list containing the class named standard-object.  
Otherwise it returns its argument {\bf supplied-superclasses}.
 

\Defmeth {class-default-direct-superclasses} {(class funcallable-standard-class) supplied-superclasses)}

If {\bf supplied-superclasses} is nil, then this method returns a list
containing the class named function and the class named object. 
Otherwise it returns its argument {\bf supplied-superclasses}.


\beginsubsubsection{Example of specializing class-default-direct-superclasses}

Suppose we have loops-class as a subclass of standard-class, and we want
all instances of loops-class to have the class named loops-object as
a default super class.

\screen!

(defclass loops-class (standard-class) ())

;;; Implement the rule that where the null superclass list is provided,
;;; return a list containing the class named loops-object.

(defmethod class-default-direct-superclasses
           ((class loops-class) supplied-superclasses)
   (or supplied-superclasses
       (list (symbol-class 'loops-object))))

\endscreen!

\endsubsubsection%{Example of specializing class-default-direct-superclasses}

\endsubsubsection%{class-default-direct-superclasses}

\beginsubsubsection{valid-superclass-p}

The generic function valid-superclass-p tests whether
the proposed superclass has a metaclass compatible with being a
direct-superclass of the class being initialized.  It returns
t if the proposed superclass is compatible, and nil otherwise.

The default method signals an error unless the metaclasses are {\bf EQ}.

\endsubsubsection%{valid-superclass-p}

\beginsubsubsection{valid-class-option-p}

This generic function is used to check the validity of class options. 
It uses {\bf or} method combination type, and returns true iff one of
the applicable methods believes that the option is legal. 

\Defmeth {valid-class-option-p}
         {(class standard-class) option}

This method checks for the allowed options described in chapter 1.

\endsubsubsection%{valid-class-option-p}
 
\beginsubsubsection{valid-slot-description-p}

This generic function is used to check the compatibility of a class and
slot-objects supplied in the call to make-instance.

\Defmeth {valid-slot-description-p}
         {(class standard-class) (slot-object standard-slot-description}

This method returns t.

\Defmeth {valid-slot-description-p}
         {(class standard-class) slot-object}

This method returns nil.  This ensures that random objects cannot be used as
a slot-description, and a reasonable error message will
be given.

\endsubsubsection%{valid-slot-description-p}

\endSubSection%{Initializing standard-class}


\beginSubSection{Readers for Standard-class}

\beginsubsubsection{class-direct-superclasses}

The value of this reader is a list of the classes that are the direct
superclasses of the given class. 
This is the value stored by initialize-instance.

Remarks: This is a storage reader. The results are
undefined if the value returned by this function is modified.

If a class has not had its direct-superclasses initialized, an error
is signalled by {\bf class-direct-superclasses}. The generic function
class-initialized-p may be used to test if this error will be signalled.

\endsubsubsection%{class-direct-superclasses}

\beginsubsubsection{class-direct-slots}

The value of this reader is a list of slot-description objects defined
directly for the given standard-class.  This is the value stored by
initialize-instance. The results are undefined if the value returned
by this function is modified.

Remarks: This is a storage reader.  


\endsubsubsection%{class-direct-slots}


\beginsubsubsection{class-direct-options}

The value of this reader is the list of class options as specified in
Chapter 1. This is the value stored by initialize-instance.

Remarks: This is a storage reader.  
The results are undefined if the value returned by this function
is modified. 

\endsubsubsection%{class-direct-options}

\beginsubsubsection{class-precedence-list}

Value: An ordered list of class objects. The first element of the list is the class itself.  For each class C on that list, and for no others,

(subtypep class C)

is true. See chapter 1 for a full description of the class-precedence-list.

Remarks:  If class-finalized-p is nil for a standard-class, an error is
signalled. Otherwise the value returned is the one stored by update-dependent. The results are undefined if the value returned by 
this function is modified.

This generic function is applicable to all the subclasses of
{\bf class}, including {\bf built-in-class} and {\bf structure-class}.    

\endsubsubsection%{class-precedence-list}

\beginsubsubsection{class-finalized-p}

The value of this reader is t if the class has been finalized by finalize-inheritance, and nil otherwise.

Remarks: class-finalized-p returns nil until its value is changed
by finalize-inheritance. Once that value becomes t, it
will always return that value. 

\endsubsubsection%{class-finalized-p}

\beginsubsubsection{class-initialized-p}

The value of this reader is t if initialize-instance has ever been called
with a value for:direct-superclasses, and is nil otherwise.   This value
is set to t by initialize-instance the first time a value has been
stored for class-direct-superclasses. 

Remarks: Class-direct-superclasses will signal an error iff
class-initialized-p returns nil.    

\endsubsubsection%{class-initialized-p}

\beginsubsubsection{class-prototype}

The value of this reader is an instance of the class.
The results are undefined if the value returned by this function is modified.    

Remarks: 
This instance may be a completely blank instance as created by
allocate-instance. The same value may be returned on each call.
The only thing guaranteed about this instance is that it will respond
properly to class-of and will select a method specialized on
this class or any subclass.  

It is not specified when this instance is created; it can be as late as
the first call to class-prototype for this class.  
The slots of this instance may all be unbound.
People who write code for print-object should take this into account.

\endsubsubsection%{class-prototype}


\beginsubsubsection{class-slots}

The value of this reader is a list of slot-description objects. 
An error is signaled if class-finalized-p is nil.
These slot-description objects are used
to determine the structure of instances of this class. 
The results are undefined if the value returned by 
this function is modified. It is the value stored by update-dependent.

\endsubsubsection%{class-slots}

\beginsubsubsection{class-direct-slot-initargs}

The value of this reader is a list of the form:

((initialization-arg-name slot-name slot-name )...)

This value is extracted from the value stored for
class-direct-slots. The result is undefined if the value returned by
this function is modified.

Remarks: The value of this reader specifies what initialize-instance
argument names can be used to initialize slots defined in this class,
and what slots they initialize.  

\endsubsubsection%{class-direct-slot-initargs}


\beginsubsubsection{class-slot-initargs}

The value of this reader is a list of the form:

((initialization-arg-name slot-name slot-name )...).    

Remarks: The value of this reader specifies what initialize-instance
argument names can be used to initialize slots defined in this class
or in any of its superclasses.

The value of this reader is dependent on the values of
class-direct-slot-initargs for all classes in its
class-precedence-list. 

The result is undefined if the value returned by
this function is modified.

\endsubsubsection%{class-slot-initargs}

\beginsubsubsection{class-direct-initargs}

The generic function {\bf class-direct-initargs} returns a list of the
names of all initialization arguments corresponding to a given class. 
These initialization arguments include those that were specified using
the {\bf :initarg} slot option in the {\bf defclass form} for the given
class, as well as those that were defined in the lambda-lists for
methods on {\bf allocate-instance} and {\bf initialize-instance} that
are defined for the exact given class.

The results are undefined if the value returned by this function is
modified.

It is permitted, but not required, for an implementation to return values
that share with internal data structures.

\endsubsubsection%{class-direct-initargs}


\beginsubsubsection{class-initargs}

This generic function returns a list of the names of all initargs that
apply to a given class, including the names of inherited initargs.
This result is the union of the following sets of the initialization
argument names: the initialization argument names contained in the result
of {\tt (class-slot-initargs {\it class\/})} and the initialization
argument names that are defined by all the applicable methods for
{\bf allocate-instance} and {\bf initialize-instance}.    

Remarks: The results are undefined if the value returned by 
this function is modified.

\endsubsubsection%{class-initargs}


\beginsubsubsection{class-direct-initarg-defaults}

The generic function {\bf class-direct-initarg-defaults} returns a
list, each of whose elements is a list consisting of the name of an
initialization argument defined for a slot in that exact class
followed by the default value function and the default initial value
form for that initialization argument.

The default value function is the function whose body is the default
initial value form; this function is created in the lexical environment of
the {\bf defclass} form that contains the default initial value form.
The default initial value form is the form that was originally specified.
It is retained only for documentation.
The results are undefined if the default initial value form is evaluated.
The default value function is what actually gets called; its effect is
equivalent to enclosing the default initial value form in the
appropriate lexical environment.  The default value function takes no
arguments.

This value is stored by initialize-instance whenever a value is provided for
class-direct-options. The results are undefined if the value returned by
this function is modified.

It is permitted, but not required, for an implementation to return values
that share with internal data structures.

\endsubsubsection%{class-direct-initarg-defaults}

\beginsubsubsection{class-initarg-defaults}

The generic function {\bf class-initarg-defaults} returns a list,
each of whose elements is a list consisting of the name of an
initialization argument defined for a slot in that class or any of its
superclasses followed by the default value function and the default initial
value form for that initialization argument.  The default value
function is the function whose body is the default initial value form; this
function is created in the lexical environment of the {\bf defclass}
form that contains the default initial value form.  The purpose of this
function is to capture the environment.

The default initial value form is the form
that was originally specified.  It is retained only for documentation.
The results are undefined if the default initial value form is evaluated.

The default value function is what actually gets called; its effect is
equivalent to enclosing the default initial value form in the
appropriate lexical environment.  The default value function takes no
arguments.

The results are undefined if the value returned by this function is
modified.

It is permitted, but not required, for an implementation to return values
that share with internal data structures.


\endsubsubsection%{class-initarg-defaults}

\beginsubsubsection{class-direct-subclasses}

The value returned by class-direct-subclasses is a list of all
classes that have this class as a direct superclass.    

The value of this reader is maintained by initialize-instance and
reinititialize-instance for standard-class through calls to
add-direct-subclass and and remove-direct-subclass.

CLOS does not specify whether this generic function has an
applicable method for built-in-class or structure-class.

\endsubsubsection%{class-direct-subclasses}

\beginsubsubsection{class-direct-methods}

The value of class-direct-methods is a list of methods
(with no duplicates) that use this class as a specializer. 

The value of this reader is maintained by add-method and remove-method
for standard-method and for standard-accessor-method through calls to
add-method-on-specializer and remove-method-on-specializer.

\endsubsubsection%{class-direct-methods}

\beginsubsubsection{class-direct-generic-functions}

The value of class-direct-generic-functions is a list of generic-functions
 (with no duplicates) that contain a method that use this class as a
specializer. 

The value of this reader is maintained by add-method and remove-method
for standard-method and for standard-accessor-method through calls to
add-method-on-specializer and remove-method-on-specializer.


\endsubsubsection%{class-direct-generic-functions}


\endSubSection%{Readers for standard-class}

\beginSubSection{Initializing standard-slot-description}

The keywords allowed as arguments for initialize-instance
of standard-slot-description are those that support the description
of slots provided in chapter 1.

\Defmetha {initialize-instance} {(class standard-slot-description)
 \&key :name :initform :initfunction :initargs :readers :writers
    :accessors :type :allocation}

Arguments:

{\bf :name}
The argument :name must be provided; otherwise an error is signalled.
It must be a symbol that can be used as a slot-name.  This value
is stored as the value for the reader {\bf slot-description-name}.

{\bf :initform}
:initform can be any Lisp form.   This value
is stored as the value for the reader {\bf slot-description-initform}.
If no value is provided, nil is stored.

{\bf :initfunction}
:initfunction must be a function of no arguments.
The purpose of this function is to capture the lexical
context of the defining defclass form. At slot initialization time,
this function is called to get an initial value for a n unbound slot.
This value is stored as the value for the reader
{\bf slot-description-initfunction}.
If no value is provided, nil is stored.

{\bf :initargs}
This is a list of symbols that can be used for slot-filling initargs
for this slot.  This value is stored as the value for the reader
{\bf slot-description-initfunction}. If no value provided, nil is stored.

{\bf :accessors}
This is a list of symbols that are to be used as names of generic
functions for readers for this slot of this class, and for which
names of the form (setf symbol) will be used as writers of this class.
The value of :accessors is used to suplement :readers and :writers.

{\bf :readers}
This is a list of symbols that are to be used as names of generic
functions for readers for this slot of this class.  The value, 
augmented by information from :accesssors, is stored as
the value for the reader {\bf slot-description-readers}.
If no value is provided, nil is stored. 

{\bf :writers}
This is a list of function specifiers that are to be used as names of
generic functions for writers for this slot of this class.  The value,
augmented by information from :accesssors, is stored as
the value of the reader {\bf slot-description-writers}.
If no value is provided, nil is stored.

{\bf :type}
This is a Common Lisp type expression.  If no value provided, t 
is stored.

{\bf :allocation}
This is one of the symbols :instance or :class.  The
value for this argument is stored as the value for the reader 
{\bf slot-description-allocation}.  This value determines how allocation for this slot will be
done.  If no value is provided, :instance 
is stored.

\endSubSection%{Initializing standard-slot-description}

\beginSubSection{Readers for standard-slot-description}

\beginsubsubsection{slot-description-name}

This reader returns the name of the slot stored by initialize instance.

\endsubsubsection%{slot-description-name}

\beginsubsubsection{slot-description-initform}

The value of this reader is the Lisp form stored by initialize-instance
as the value of the :initform option. 

\endsubsubsection%{slot-description-initform}

\beginsubsubsection{slot-description-initfunction}

The value of this reader is the Lisp function stored by initialize-instance
as the value of the :initfunction option. 

\endsubsubsection%{slot-description-initfunction}

\beginsubsubsection{slot-description-type}

The value of this reader is a Common Lisp type specifier.  The value is
the one passed in to the call to initialize-instance.

\endsubsubsection%{slot-description-type}

\beginsubsubsection{slot-description-allocation}

The value of this reader for standard-class is one of :instance or
:class.  It is the value stored by initialize-instance. 

\endsubsubsection%{slot-description-allocation}

\beginsubsubsection{slot-description-initargs}

The value of this reader is a list of symbols that can be used as a
slot-filling initarg for this slot.  

\endsubsubsection%{slot-description-initargs}

\beginsubsubsection{slot-description-readers}

The value of this reader is the list stored by initialize-instance
constructed from the :readers and :accessors options.  

\endsubsubsection%{slot-description-readers}

\beginsubsubsection{slot-description-writers}

The value of this reader is a list stored by initialize-instance
constructed from the :writers and :accessors options.  

\endsubsubsection%{slot-description-writer-names}

\endSubSection%{Readers for standard-slot-description}


\beginSubSection{Initialization for Methods}

\Defmetha {initialize-instance} {(class standard-method)
    \&key :lambda-list :specializers :qualifiers :function}

The :lambda-list, :specializers and :function must be provided.
The :qualifiers will default to nil. 

{\bf :lambda-list}
The lambda-list argument is a CLtL lambda-list.  It must specify the 
{\it natural} arguments to the function provided as the :function
argument to initialize-instance.  The behavior is undefined if
this contract is
not met.  When this method is added to a generic function, the congruence
of this lambda list will be checked against the lambda-list of the
generic function.

{\bf :specializers}
This must be a list whose  length is equal to the the number of
required arguments in the lambda-list.  Its elements must be parameter
specializers as defined in Chapter 1.

{\bf :qualifiers}
This must be a list of non-nil atoms.  See Chapter 1.

{\bf :function}
This argument must be a function that satisfies method-function-p.
See the description of this in the next section.  This function must take
as arguments at least those specified by lambda-list.  Again, see the
discussion of method-lambda in the section on Method Functions.

{\bf :documentation}
This is a string used to document this method.  It will be
accessible by the generic-fucntion {\bf documentation}.  If no
value is provided, the empty string is stored.
 

\endSubSection%{Initialization for Methods}

\beginSubSection{Method Functions}

In order to capture the contract that a generic function and method
must support between them, an implementation may need to be pass
additional information into a method at run time: for example, 
the list of next methods for call-next-method, or a permutation vector
for optimized access to slots of some class, etc. 
We support this abstraction by introducing three new
constructs: method-lambda, method-function-p and apply-method-lambda. 

\beginsubsubsection{method-lambda}

The special form method-lambda is
used for constructing functions in exactly the same way lambda
is used to construct ordinary functions, except that the functions it
produces are designed to be called with apply-method-lambda.
The number of arguments for the function it constructs may be
different than the number explicit in the lambda-list of the form.
The results of calling a method-lambda with ordinary apply are undefined.

The predicate method-function-p can be used to test if a function
was created with method-lambda.

\endsubsubsection%{method-lambda}

\beginsubsubsection{method-function-p}

The predicate method-function-p returns true if its argument is a function created with method-lambda, and return nil otherwise.

\endsubsubsection%{method-function-p}


\beginsubsubsection{apply-method-lambda}

The function apply-method-lambda is like apply. 
It takes the 'natural' arguments that
want to be passed to the method function.  It does anything else that
needs to be done to call the method-function properly.  
Any call to  call-next-method inside of the called method-function
would signal an error indicating there were no next methods.

Here is some sample code.

\screen!
(defun trace-gf (gf)
  (let ((nargs (generic-function-required-arguments gf))
        (lambda-list (generic-function-lambda-list gf))
        (specializers (make-list nargs :initial-element (symbol-class 't)))
        (qualifiers '(:around))
        (function (compile () `(method-lambda ,lambda-list
                                 (format *trace-output* "~&Hi there.")
                                 (call-next-method)))))
    (add-method gf
                (make-instance 'standard-method
                               :lambda-list lambda-list
                               :specializers specializers
                               :qualifiers qualifiers
                               :function function))))

\endscreen!


\endsubsubsection%{apply-method-lambda}

\endSubSection%{Method Functions}

\beginSubSection{Readers for standard-method}

For all of these readers, the discussion in chapters 1 and 2 should be consulted.

\beginsubsubsection{method-generic-function}

The value of this reader is the generic function object of
which this method is a part.  This reader returns nil
if this method is not on a generic function.
The value returned by this reader is maintained by add-method and remove-method.  

\endsubsubsection%{method-generic-function}

\beginsubsubsection{method-lambda-list}

The value of this reader is the lambda-list stored by
initialize-instance.  The results are undefined if the
value returned by this function is modified.

\endsubsubsection%{method-lambda-list}

\beginsubsubsection{method-specializers}

This is a list of parameter specializers for this method as specified in
Chapter 1. The value of this reader is the list of specializers stored by
initialize-instance.  The results are undefined if the value returned by 
this function is modified.

\endsubsubsection%{method-specializers}

\beginsubsubsection{method-qualifiers}

This is a list of qualifiers for this method. It is a list of non-nil
atoms. The value of this reader is the :qualifiers argument
stored by initialize-instance.
The results are undefined if the value returned by 
this function is modified.

\endsubsubsection%{method-qualifiers}


\beginsubsubsection{method-function}

The value of this reader is the method function  stored as the :function
argument by initialize-instance.

\endsubsubsection%{method-function}

\endSubSection%{Readers for standard-method}

\beginSubSection{Initializing standard-accessor-methods}

Standard-accessor-methods are the automatically generated methods
that support the access to slots of classes, as specified
by the :reader and :writer slot options for defclass.  

These are generated by the update-dependent method on standard-class.
It cannot be generated by initialize-instance since a class may
not yet be fully defined when initialize-instance is called.
Everything said here is true for both instances of standard-reader-method
and standard-writer-method.  Users can can create instances of
these methods using make-instance.

\Defmetha {initialize-instance} {(class standard-accessor-method)
    \&key :applicable-class :slot-name}

{\bf :applicable-class}
This argument is a class-object.  The specializer list for this method
is simply (list :applicable-class).

{\bf :slot-name}
is the name of slot in applicable-class.
An error is signalled if this is not true when the method is created..  

Method objects that are instances of standard-reader-method
(standard-writer-method) supports reading (writing) the value of
this slot in instances of applicable-class.

The value stored for the reader method-lambda-list for
these accessor methods is:

(list (or (class-name applicable-class) 'object))

for readers, and

(list 'new-value (or (class-name applicable-class) 'object))
 
for writers.

\endSubSection%{Initializing standard-accessor-methods}

\beginSubSection{Readers for standard-accessor-method}

\beginsubsubsection{method-applicable-class}

This method returns the applicable-class stored by initialize-instance.
This method will be applicable to instance of this class, and all
its subclasses.

\endsubsubsection%{method-applicable-class}


\beginsubsubsection{method-slot-name}

This method returns the slot-name stored by initialize-instance.

\endsubsubsection%{method-slot-name}

\beginsubsubsection{method-generic-function}

The value of this reader is the generic function object of
which this method is a part.  This reader returns nil
if this method is not on a generic function.
The value returned by this reader is maintained by add-method and remove-method.  

\endsubsubsection%{method-generic-function}

\beginsubsubsection{method-lambda-list}

The value of this reader is described above in the section
on initialize-instance. The results are undefined if the value
returned by this function is modified.

\endsubsubsection%{method-lambda-list}

\beginsubsubsection{method-specializers}

The value of this reader is a list of one element,
the applicable-class. This value is stored by
initialize-instance for standard-sccessor-method.
The results are undefined if the
value returned by this function is modified.

\endsubsubsection%{method-specializers}

\beginsubsubsection{method-qualifiers}

This method always returns nil for accessor methods.

\endsubsubsection%{method-qualifiers}

\endSubSection%{Readers for standard-accessor-method}


\beginSubSection{Initializing Standard-generic-function}

Generic function objects are both like standard-objects in the
sense that they maintain state that can be accessed by readers, and
funcallable objects in the Common Lisp sense.  

Generic function objects are intrinsically anonymous.  They have names
in the same sense that ordinary function objects do; that is, they may
appear in the symbol-function cell of some function specifier.  In the
creation and initialization of these objects, there is no way to specify
a name.  But see the reader generic-function-name below for a way to
associate a hint about a name with these objects.

The initialize-instance method is what is called by ensure-generic-function
to initialize an instance of the generic function.  We mention this here
only because the constraints on the arguments to initialize-instance
and reinitialize-instance described below are just those that support
the capabilities described for ensure-generic-function.

\Defmetha {initialize-instance} {(class standard-generic-function)
    \&key :lambda-list :argument-precedence-order :declare
          :documentation :method-class :method-combination :methods}

{\bf :lambda-list}
This is a lambda-list of the form described for defgeneric. The lambda-list
argument must be provided or an error is signalled.

{\bf :argument-precedence-order}
This is a list which is a permutation of the names of the required
arguments in the lambda-list.  If no value is provided it defaults
to a list of the required arguments of the lambda-list, in
the same order as in the lambda list.

{\bf :declare}
This is a form that specifies declarations applicable to the generic
function as a whole.  See the description in defgeneric.
If no value is provided, it defaults to (). 

{\bf :documentation}
This is a string describing the generic function.

{\bf :method-class}
This must be a class object that will be used to create instances
of methods for this generic function that are defined using 
the method defining forms.
If it is not provided it defaults to (symbol-class 'standard-method).

{\bf :method-combination}
This is a method combination object.  If it is not provided it defaults
to an instance of (symbol-class 'standard-method-combination). See the
description below of expansion of the user interface macro forms.

{\bf :initial-methods}
This is a list of method objects.  These are methods that are stored
as the value of generic-function-initial-methods.
In addition, any of these methods which is not on the generic
function is added to the generic function.  If the generic function is
reinitialized, each of these methods will be 
removed from the generic function.  See method-reinitialization.

\endSubSection%{Initializing Standard-generic-function}

\beginSubSection{Readers for Standard-generic-function}

\beginsubsubsection{generic-function-name}
The value returned by this reader is a function specifier or nil.
This value is a hint for the environment.  In general, one cannot count
on the following identity:

(eql (symbol-function (generic-function-name g-fn)) g-fn)
 
There is a setf generic function associated with generic-function-name.
This may be used to change the value returned by this reader.  

\endsubsubsection%{generic-function-name}

\beginsubsubsection{generic-function-lambda-list}

This is the lambda-list stored by initialize-instance.  It is also
the lambda list of the generic function considered as a functional object.

The results are undefined if the value returned by this reader is modified.

\endsubsubsection%{generic-function-lambda-list}

\beginsubsubsection{generic-function-argument-precedence-order}

This is the list stored by initialize-instance as the value for
:argument-precedence-order.  It is a permutation of the list of 
required arguments of the generic-function-lambda-list.

The results are undefined if the value returned by this reader is modified.

\endsubsubsection%{generic-function-argument-precedence-order}

\beginsubsubsection{generic-function-method-class}

This is the class object stored by initialize-instance as the value for
:method-class.  The value of this reader will be used in the creation
of method objects for this generic function defined using defclass.

\endsubsubsection%{generic-function-method-class}

\beginsubsubsection{generic-function-declarations}

This value is the form stored by initialize-instance from the
:declare argument.  

The results are undefined if the value returned by this reader is modified.

\endsubsubsection%{generic-function-declarations}

\beginsubsubsection{generic-function-method-combination}

This is the method-combination object stored by initialize-instance
as the value for :method-combination.  The value of this reader will be 
used in the creation of the effective code for method combination.

The results are undefined if the value returned by this reader is modified.

\endsubsubsection%{generic-function-method-combination}

\beginsubsubsection{generic-function-methods}

The results of this reader is a list of methods defined on this generic
function.  This list is updated by add-method and remove-method.

The results are undefined if the value returned by this reader is modified.

\endsubsubsection%{generic-function-methods}

\beginsubsubsection{generic-function-initial-methods}

The results of this reader is a list of methods defined on this generic
function at initialization or reinititialization.  These methods are also
elements of the list returned by generic-function-methods.  This list of
methods is updated to the most recent value for the :initial-methods argument of
initialize-instance.

The results are undefined if the value returned by this reader is modified.

\endsubsubsection%{generic-function-initial-methods}

\beginsubsubsection{method-applicable-keywords}

The purpose of this generic function is to deliver to the user a list of the
keyword arguments that are legal for a particular set of arguments for
a generic function.

\Defmeth {method-applicable-keywords} {(g-fn standard-generic-function)
    list-of-required-arguments}

The function returns a list of keywords (possibly nil).  If
\&allow-other-keys is a member of the list, then any keyword argument
will be legal in the call.  

\endsubsubsection%{method-applicable-keywords}
\beginsubsubsection{add-method, remove-method, get-method}

The generic functions add-method and remove-method have
been described in chapter 2.  They are the only acceptable mechanism
for updating the set of methods on a generic function.
The methods on standard-generic-function and standard-method both
call {\bf generic-function-changed} when they actually make a change.
The standard method on add-method calls add-method-on-specializer.
The standard method on remove-method calls remove-method-on-specializer.

The generic function get-method can be used to locate a method that has a particular set of specializers on a generic function.

\endsubsubsection%{add-method, remove-method, get-method}

\beginsubsubsection{add-method-on-specializer}

\Defmeth {add-method-on-specializer} {(method method)(class standard-class)}

 
Whenever a method is added to a generic-function, this method is
called on every class specializer for the method.  It updates
the values of class-direct-methods and class-direct-generic-functions
for the class.

\endsubsubsection%{add-method-on-specializer}

\beginsubsubsection{remove-method-on-specializer}

Whenever a method is removed from a generic-function, this method is
called on every class specializer for the method.  It updates
the values of class-direct-methods and class-direct-generic-functions
for the class.
  
\endsubsubsection%{remove-method-on-specializer}

\endSubSection%{Readers for Standard-generic-function}


\beginSubSection{Initializing Method Combination Objects}

There are two classes of method combination objects defined in the
standard: standard-method-combination and simple-method-combination.

\Defmetha {initialize-instance} {(method-combination standard-method-combination)
    \&rest initargs}

This method has no initialize-instance arguments, since it has no
state that is special.  What is missing is a description of the expected
arguments for a new class defined by define-method-combination.

\Defmetha {initialize-instance} {(class simple-method-combination)
    \&key :name :order :operator :identity-with-one-argument :documentation}

This method supports the creation and initialization of objects
for the short form of method-combination as specified in Chapter 2.

{\bf :order}
This argument is one of the two values {\bf :most-specific-first} or
{\bf :most-specific-last}.  If it is not provided, it defaults to 
{\bf :most-specific-first}.

{\bf :operator}
This argument is the name of an n-ary Lisp function. 

{\bf :identity-with-one-argument}
This argument is a boolean which is t if the optimization
described in chapter 2 is possible, else nil.

{\bf :documentation}
This argument is a string used to document this simple-method-combination.
It will be stored in a way that will make it accessible by the
generic function {\bf documentation}.

\endSubSection%{Initializing Method combination objects}

\beginSubSection{Readers for Method combination objects}

\beginsubsubsection{method-combination-name}

This generic function returns the name used by
method-combination-object to identify this method combination type.
For standard-method-combination the value is 
{\bf standard-method-combination} 

See the description later of method-combination-object in the section on
expanding the user macros.  

\endsubsubsection%{method-combination-name}

\beginsubsubsection{method-combination-options}
This generic function returns the options used by
method-combination-object to identify this method combination type.
For standard-method-combination the value is nil.
See the description later of method-combination-object in the section on
expanding the user macros.  

\endsubsubsection%{method-combination-options}

\beginsubsubsection{method-combination-order}

\Defmeth {method-combination-order} {(method-combination simple-method-combination)}

Returns the value of the argument :order given to initialize-instance.

\endsubsubsection%{method-combination-order}

\beginsubsubsection{method-combination-operator}

\Defmeth {method-combination-operator} {(method-combination simple-method-combination)}

Returns the value of the argument :operator given to initialize-instance.

\endsubsubsection%{method-combination-operator}

\beginsubsubsection{method-combination-identity-with-one-argument}

\Defmeth {method-combination-identity-with-one-argument} {(class simple-method-combination)}

Returns the value of the argument :identity-with-one-argument given to initialize-instance.

\endsubsubsection%{method-combination-identity-with-one-argument}

\endSubSection%{Readers for Method combination objects}

\endSection%{The Classes in the CLOS Kernel}

\beginSection{Reinitialization and Updating Dependents}

CLOS supports a general notion of reinitialization for standard-objects,
and the recording and updating of dependent objects when an object is
changed.  The generic-function {\bf reinitialize-instance} invokes 
{\bf initialize-instance} to make changes to the state of an object, and
then calls {\bf update-dependents} to update any objects that have registered
themselves as dependent on the state of the changed object.  The generic
function {\bf add-dependent} is used to register the dependence of one
object on the state of another, and {\bf remove-dependent} is used unregister
the dependence.  The generic function {\bf update-dependent} does the
updating.

\beginsubsubsection{reinitialize-instance for standard-object}

Following is  some model code for the method on standard-object.

\screen!

(defmethod reinitialize-instance :before
     ((object standard-object) &rest reinit-args)
  ;; signals an error on bad arguments
  (check-reinitargs object reinit-args))

(defmethod reinitialize-instance 
     ((object standard-object) &rest reinit-args)
  ;; reuse initialization methods
   (apply #'initialize-instance 
                     object 
                     :allow-other-keys 't
                     reinit-args))

(defmethod reinitialize-instance :after
    ((object standard-object) &rest reinit-args)
  ;; updates dependents
   (apply #'update-dependents object reinit-args))

\endscreen!


Note that reinitialize-instance does not use default-initargs.
Nor does it automatically make any of the slots of object be unbound.
Hence in initialize-instance, only those arguments
explicitly given will affect the object.  Values for slot-filling
initargs will be stored.  Initforms will be evaluated and stored
only for slots that are unbound.  
Programs can call slot-makunbound for particular
slots, to cause those slots to be reinitalized from the intiforms.

\endsubsubsection%{reinitialize-instance for standard-object}
\beginsubsubsection{check-reinitargs}

This ensures that the arguments given are acceptable to either
initialize-instance or to a method of reinitialize-instance
itself.

\screen!

(defmethod check-reinitargs 
    ((object standard-object) reinit-args)
  (let* ((arglist (list object))
	    (acceptable-args
           (union
             (method-keyword-arguments #'initialize-instance arglist)
             (method-keyword-arguments #'reinitialize-instance arglist)
             (class-all-slot-initargs (class-of object)))))
    (zl:loop (key in reinit-args by cddr)
       (unless (member key acceptable-args) (error ...))))
\endscreen!

\endsubsubsection%{check-reinitargs}

\beginsubsubsection{update-dependents}

There is a set of generic functions for managing the dependents of an
object.  This is part of the instance re-initialization protocol.  How
dependents are  stored is implementation dependent.  Some subclasses
of standard-object which know that they are in fact going to have lots
of dependents may want to replace the general methods with specialized
mechanisms for storing  the dependents (e.g. using a slot)

The set of generic functions include add-dependent, remove-dependent,
map-dependents, for managing the data base, and update-dependents and
update-dependent for doing the update.


The standard method on update-dependents  maps through all the dependents of the object, calling update-dependent.  Although
the standard method makes use of the database, for special cases
update-dependents may have its own way of updating the dependents without
mapping through a list of registered dependents
 
\screen!

(defmethod update-dependents ((object standard-object) &rest update-args)
  (map-dependents
     object
     #'(lambda (changed-object dependent update-args)
         (apply #'update-dependent changed-object dependent update-args))
     update-args))

\endscreen!

 \endsubsubsection%{update-dependents}
 
\beginsubsubsection{map-dependents}

\Defgen {map-dependents} {object map-fn other-args}
 
This generic function expects the object, a function and a list of
other-args.  It finds each registered dependent and does:

(apply \#'map-fn object dependent other-args)

The key difference between methods on this generic function are how
dependents are found.

\endsubsubsection%{map-dependents}

\beginsubsubsection{add-dependent}

This generic function adds a dependent to the set of dependents.
If the dependent is already a member, it is not added again.

\endsubsubsection%{add-dependents}

\beginsubsubsection{remove-dependent}

This generic function removes a dependent from the set of dependents.
If the dependent is not a member, it is a noop.

\endsubsubsection%{remove-dependents}

\beginsubsubsection{update-dependent - no default method}

\Defgen {update-dependent} {object \&rest update-args}

This generic function is meant to do whatever is necessary
to update dependent found by map-dependent. 
There is no method for update-dependent on standard-object
so that calls to update-dependent that have no applicable
method will signal an error.

Update-dependent methods are not supposed to recursively
invoke update-dependent again.  The intention is that all dependents should
be recorded with add-dependent.

\endsubsubsection%{update-dependent on standard-object}


\beginsubsubsection{reinitialize-instance for standard-class}

The reinitialize-instance method for standard-class is used to modify an
existing class definition.  One time that this happens is when
add-named-class is called and there is already a class by that name.
when a defclass form is reevaluated. All subclasses that need
to be informed when a class has changed must register themselves as
dependents using add-dependent.  A specialized method on update-dependent
is used to propogate all necesary changes to the subclass. 
 
The only specialized method for {\bf reinitialize-instance}
for standard-class is:

\screen!

The keywords accepted by this method are just those of
initialize-instance for standard-class.

(defmethod reinitialize-instance  ((class standard-class) &rest reinit-args)
   (let ((old-direct-super-classes (class-direct-superclasses class))
     (call-next-method)
     (let ((new-direct-super-classes (class-direct-superclasses class))
        (dolist (c (set-difference
                      old-direct-super-classes
                      new-direct-super-classes))
          ;;remove obsolete direct subclass links
          ;;initialize-instance adds the links for new subclasses
                (remove-direct-subclass c class))
        )))
\endscreen!

This method maintains the links to subclasses.

\endsubsubsection%{reinitialize-instance for standard-class}

\beginsubsubsection{add-direct-subclass}

\Defmeth {add-direct-subclass}
  {(class standard-class) (subclass standard-class))}

This generic function adds subclass to the value
of class-direct-subclasses for superclass.  This generic function
is called by {\bf initialize-instance} for standard-class. 
It is a noop if subclass is already a member of class-direct-subclasses.

\endsubsubsection%{add-direct-subclass}

\beginsubsubsection{remove-direct-subclass}

This generic function removes the subclass from the value
of class-direct-subclasses for superclass.  This generic function
is called by {\bf reinitialize-instance} for standard-class. 
It is a noop if subclass is not a member of class-direct-subclasses.

\endsubsubsection%{remove-direct-subclass}

\beginsubsubsection{update-dependent for standard-class}

This method maintains classes when changes have occurred in the
class lattice above them.  It also called by finalize-inheritance
to cause inherited information to be collected in the class.
The system-supplied method may conspire with
methods for {\bf make-instance}, {\bf default-initargs},  {\bf
check-initargs}, {\bf allocate-instance}, and {\bf initialize-instance}
to speed up object creation by precomputing information.  This
optimization is implementation dependent, but the {\bf update-dependent}
mechanism that makes such optimizations possible is standardized.

Users with special optimization needs can write methods for
{\bf update-dependent} to precompute information based on inherited
information and to update the precomputed information whenever changes
occur.

The update-dependent code has an :around method to take care of
class-access-keys and obsoleting instances if necessary.

\screen!
  (defmethod update-dependent :around ((reinitialized-class standard-class)
     				     (dependent standard-class)
     				     &rest other-args)
           ;; Implementation specific code to account for the fact that
           ;; the access keys for this class may change. This is required to
           ;; cause the optimization of standard-instance-access to
           ;; continue to work.
           ;; This may call make-instance-obsolete.
           )))
\endscreen!

The main method is used to collect information in the class from classes it
inherits from.  It computes the class-precedence-list 
by calling the generic function compute-class-precedence-list.
This value is stored as the value for the reader class-precedence-list.
It registers this class as a dependent of every class on its
class-precedence-list.   

It computes the list of all slots by calling collect-slot-descriptions.
This value is stored as the value for the reader class-slots.

When reinitialized-class = dependent, it goes through the slots
and creates readers and writers as specified.

It collects values of default-initargs for dependent.

It may do other implemenation dependent actions.

\screen!
(defmethod update-dependent ((reinitialized-class standard-class)
     			     (dependent standard-class)
     			     &key direct-superclasses
     				  direct-slots
     				  direct-options)
       ;; When we are called,there are two cases.  In one case
       ;; this method has been called from finalize-inheritance
       ;; In this case, the old cpl, slots, and generated
       ;; readers and writers are nil. We can check this case by
       ;; using the predicate class-finalized-p.
       ;; In the general case, the dependent is finalized.  We
       ;; have to do whatever updating is required to keep us finalized.
       ;; This includes:
       ;;  - recomputing our class-precedence-list
       ;;    go through the old and new cpls, calling remove-dependent
       ;;    and add-dependent to update our dependents.
       ;;  - recomputing our slots, this may change the value that
       ;;    class-access-keys will be returning.
       ;;  - go through the old and new slots adding and removing
       ;;    automatically generated reader and writer methods as
       ;;    required.
       ;;  - update the effect of class-options
       )

\endscreen!

Note that this update-dependent method is not recursive.  
Indirect dependency of classes is not supported.
All classes that depend in any way on
a possible class must register themselves directly as dependents.


\endsubsubsection%{update-dependent for standard-class}

\beginsubsubsection{finalize-inheritance}

The purpose of this generic function is to inform a class that it should
ensure that all inherited information is now collected in the class.
This generic-function is expected to be called only once.  For
standard-class, it is a noop to do it a second time, since update-dependent
is expected to maintain the collected information once it has been
stored.  All the work of for standard-class is done by calling
 
  (update-dependent class class)


\endsubsubsection%{finalize-inheritance}


\beginsubsubsection{reinitialize-instance for slot-description}

Slot description objects are immutable after creation.  An error is signalled
if an attempt is made to reinitialize a slot-description object.

\endsubsubsection%{reinitialize-instance for slot-description}

\beginsubsubsection{reinitialize-instance for methods}

An error is signalled if an attempt is made to reinitialize a
method while it is on a generic function.
Otherwise, any of the arguments to initialize-instance will override the
currrent value in the method.  It is undefined what happens
if the :function and the :lambda-list are changed in incompatible ways. 

\endsubsubsection%{reinitialize-instance for methods}


\beginsubsubsection{reinitialize-instance for method-combination objects}

Method combination objects are immutable after creation.  
An error is signalled if an attempt is made to reinitialize a
method-combination object.

\endsubsubsection%{reinitialize-instance for method-combination objects}

\beginsubsubsection{reinitialize-instance for standard-generic-function}

The reinitialize-instance behavior for generic-functions supports the
specified behavior of ensure-generic function.

\Defmeth {reinitialize-instance} {(g-fn standard-generic-function)
    \&key :lambda-list :argument-precedence-order :declare
          :documentation :method-class :method-combination :methods}

This method checks the new value of lambda-list, then removes previous
initial-methods and does a call-next-method.
Any of the arguments that are not provided, except methods default to their
previous value.  If there are any changes, it calls generic-function-changed.

{\bf :lambda-list}  If the lambda-list is not congruent to the
current lambda-list, and the generic function has methods, then an error is
signalled.

Other arguments are checked by initialize-instance.

\endsubsubsection%{reinitialize-instance for standard-generic-function}

\beginsubsubsection{generic-function-changed}

\Defmeth {generic-function-changed} {(g-fn standard-generic-function)
    \&key :argument-precedence-order-changed :declare-changed
       :method-combination-changed :method-added :method-removed}

The standard method on generic-function-changed takes arguments
which let it know what has changed that may affect the code for the
generic-function. Except for methods-added and methods-removed,
these are all flags.  

This generic function is called by reinitialize-instance for
standard-generic-function, and by add-method and remove-method.
 
\endsubsubsection%{generic-function-changed}


\endSection%{Reinitialization and Updating Dependents}

\beginSection{Expansions of the User Macros}

\beginSubSection{Expanding defclass forms}

As with all objects in CLOS, there is a complete separation of the
object space from any naming that is done.  As explained in
chapters 1 and 2, symbol-class is used to map from names to classes.

We do not specify what the function is that expands the defclass
macro.  It must do any system dependent and programming 
environment specific operations such as recording the locations 
of definitions on files etc. It is also allowed (encouraged) to use valid-slot-option-p and valid-class-option-p to check for errors to
give early and better error messages than would occur at the time
initialization takes place.

The defclass macro expands to a call to add-named-class.  
The  first argument to add-named-class is a prototype-instance
of the class specified by the :metaclass option in the defclass form.
This allows class specific methods to be used for the actual definition
of the class before having in hand the exact object that is the class.
The other arguments for add-named class are just the obvious pieces of
the defclass form. 

\beginsubsubsection{add-named-class}

This generic function is the programmatic interface for defining named
classes.  The first argument should be the class-prototype
of the metaclass of the class being defined.    

\Defmeth {add-named-class} {(class standard-class)
    \&key :name :super-names :slot-specifications :direct-options :environment}

The :super-names argument can be a list of either symbols (class names)
or class objects. The slot-specifications argument should be a list of slot
specifications as they would appear in a defclass form.  
The direct-options should be a list of the class
options as they would appear in a defclass form.  The environment is the
macroexpansion environment of the defclass form. 
This is the \&environment argument
passed to the function that expands defclass.  

If there is no class with the given name, a new class is created.
If there is already a class with the given name the results depends
on the metaclass.

The standard method on add-named-class implements the behavior described
for defclass in chapter 1.

If :super-names is provided, then it is normalized to a list of class
objects as follows. 

\screen!

(mapcar
   #'(lambda(s)
      (cond((typep s 'class) s)
           ((or (null s)(not (symbolp s))) (error ...))
           ((cboundp s) (symbol-class s))
     ;; create a standard-class named s with no direct-superclasses
     ;; this supports the forward-referencing of standard-class
     ;; this uninitialized class can be reinitialized
     ;; but will cause an error if any of its subclasses has its
     ;; inheritance finalized
           (t (add-named-class
               (class-prototype (symbol-class 'standard-class))
                    :name s)))))
   direct-superclasses)

\endscreen!

This normalized list is used as the value for direct-superclasses.

The next step performed by this method is to determine the class object
which will be used for the new definition. If there is already a class
with the given name, this method calls the generic function
class-for-redefinition to get the class object to use.  

The slot-specifications are parsed to turn them into slot description
objects.  The class-prototype is used to determine the form
of the slot-description objects.  For details, see the slot parsing protocol. 

If there was no existing class with the given name, make-instance is called
using the metaclass specified, passing in the computed list of
direct-superclass objects, the the computed set of slot-description objects,
and the options as specified.  It makes the resulting class have as a proper name the value of :name.


If class-for-redefinition was called, the resulting class will be reinititialized using reinitialize-instance using the same arguments specified above.

\endsubsubsection%{add-named-class}

\beginsubsubsection{class-for-redefinition}


\Defgen {class-for-redefinition} {prototype-instance old-class}

class-for-redefinition is called by the standard method on
add-named-class when there is already a class with the given name.  The
class-for-redefinition generic function is expected to return the class
object which should be used for the new definition.  For standard-class,
the class object used is the old class object since standard class
supports the notion of updating old instances to reflect new definitions
of the class.  Other metaclasses might not support this notion, they
might want new class definitions to use a new class object or even
signal an error if an attempt is made to redefine a class.

\Defmeth {class-for-redefinition} {(prototype-instance standard-class)
                                   (old-class standard-class)}

This method returns the old-class argument.


Example Specialization of class-for-redefinition

Sometimes, a user wants to declare that certain classes, when they are
defined, should have a particular metaclass.  This can be the case
when someone takes a program which is already written and wants to
compile and load it using an optimizing metaclass. The user explicitly
does not want to have to edit the original defclass forms to specify the
metaclass option; the user would like to use a simple macro to make this
declaration.  Something like:

\screen!

(defclass-optimized A)

\endscreen!

Given that the optimizing metaclass already exists and is called
optimized-class, this can be done using class-for-redefinition.  The
following code will work.

\screen!

(defclass forward-referenced-optimized-class (forward-referenced-class)
    ())

(defmethod class-for-redefinition
           ((existing-class forward-referenced-optimized-class)
            (proposed-new-class standard-class)
            &rest other-args)
  (change-class existing-class
                (class-prototype (symbol-class 'optimized-class)))
  existing-class)

(defmacro defclass-optimized (class-name)
  `(add-named-class
     (class-prototype (class-named 'forward-referenced-optimized-class))
     :name ',class-name))

\endscreen!


\endsubsubsection%{class-for-redefinition}

\endSubSection%{Expansion of Defclass}

\beginSubSection{Expansion of defgeneric}


The defgeneric form is expanded into a call to ensure-generic-function, and
a defmethod method for each :method option that appears in the defgeneric form.  The :methods argument for reinitialize-instance is a list of the
method objects created by these defmethods. 
    
The method-combination argument to ensure-generic-function is computed
by the generic function {\bf method-combination-object} applied to the
method-combination option of defclass.

The expansion of a defgeneric is approximately

\screen!
(let((g-fn
   (ensure-generic-function <name>
     :method-combination (method-combination-object <meth-comb-arg>)
    ...))) ;; include other arguments directly from defgeneric
  (reinitialize-instance g-fn
     :methods (list (defmethod ...) (defmethod ...))))
\endscreen!
   

\beginsubsubsection{method-combination-object}

The purpose of {\bf method-combination-object} is to convert a method
combination name and a list of options into an object.


\Defgen {method-combination-object} {method-combination-name method-combination-options}

It returns as a value a method-combination object.
  
{\bf method-combination-object} signals an error if
method-combination-name is unrecognized.  Each method for
{\bf method-combination-object} signals an 
error if the method-combination-options are unrecognized or
there are too many or too few of them.

{\bf method-combination-object} might return the same object each time it is called with given arguments, or it might make a new object.

\Defmeth {method-combination-object} {(name (eql nil)) options}

This method returns an instance of standard-method-combination.
This method is used to compute the default method combination object when
no argument is given to defgeneric.

\Defmeth {method-combination-object}
   {(name (eql 'standard-method-combination)) options}
 
This method also returns an instance of standard-method-combination.

\endsubsubsection%{method-combination-object}

\endSubSection%{Expansion of defgeneric}


\beginSubSection{Expansion of defmethod}

A defmethod form expands into

(add-named-method function-specifier method-qualifiers method-lambda-list
    method-lambda-form)

for example,

\screen!

(defmethod (setf foo) :before ((x c1) y &rest z) (do-foo ...))

would expand into

(add-named-method  '(setf foo)  '(:before)
  '((x c1) y &rest z) (method-lambda (x y &rest z) (do-foo ...)))

\endscreen!
 
\beginsubsubsection{add-named-method}

The purpose of {\bf add-named-method} is to a a method to the a named generic function.  Some model code for for this function is:

\screen!

(defun add-named-method
    (name qualifiers method-lambda-list method-lambda-fn)
  (let* ((g-fn (ensure-generic-function  name))
         (method (make-instance (generic-function-method-class g-fn)
                   :method-function method-lambda-fn
                   :qualifiers qualifiers
                   :lambda-list (strip-lambda-list method-lambda-list))))
    (add-method g-fn method)
    method))

\endscreen!


\endsubsubsection%{add-named-method}

\endSubSection%{Expansion of defmethod}

\beginSubSection{Expansion of define-method-combination}

define-method-combination expands into a defmethod for
method-combination-object.   {\bf remove-method} can be used to
undefine a method combination type. 

All invocations of the short form of define-method-combination 
define methods which return instances of the class simple-method-combination.

Each invocation of the long form of define-method-combination defines
a new class which has a superclass in common with standard-method-combination.
CLOS does not specify how many of these classes there are nor what
their names are.

Example:

\screen!

The short form of define-method-combination could have been defined
as follows:

(defclass short-form-method-combination
          (method-combination)
          ((name :initarg name :reader method-combination-name)
           (order :initarg order)
           (documentation :initarg documentation :reader documentation)
           (operator :initarg operator)
           (identity-with-one-argument :initarg identity-with-one-argument)))

(defmethod method-combination-options ((mc short-form-method-combination))
  (list (slot-value mc 'order)))

(defmethod compute-effective-method (generic-function
                                     methods
                                     (mc short-form-method-combination))
  (let ((primary-methods (remove (list (slot-value mc 'name))
                                 methods :key #'method-qualifiers
                                 :test-not #'equal))
        (around-methods (remove '(:around)
                                methods :key #'method-qualifiers
                                :test-not #'equal)))
  (when (eq (slot-value mc 'order) ':most-specific-last)
    (setq primary-methods (reverse primary-methods)))
  (dolist (method (set-difference methods
                                  (union primary-methods around-methods)))
    (invalid-method-error method "The qualifiers of ~S, ~:S, are not ~S or ~S"
                          method (method-qualifiers method)
                          (list (slot-value mc 'name)) '(:around)))
  ;;--- Note: this example has not been updated to reflect the removal
  ;;--- of make-method-call.  If we do that, the update should be
  ;;--- straightforward.
  (make-method-call `(,@around-methods
                      ,(make-method-call primary-methods
                                         :operator (slot-value mc 'operator)
                                         :identity-with-one-argument
                                           (slot-value mc 'identity-with-one-argument)))
                    :operator :call-next-method)))

(defmethod describe-method-concisely
           (generic-function
            method
            (method-combination short-form-method-combination))
  (declare (ignore generic-function))
  (write-string (string-downcase (string (first (method-qualifiers method))))))

(defmacro define-method-combination
          (name &key (documentation nil)
                     (operator name)
                     (identity-with-one-argument nil))
  `(defmethod method-combination-object
              ((name (eql ',name))
               options)
     (apply #'(lambda (&optional (order ':most-specific-first))
                (check-type order (member :most-specific-first
					  :most-specific-last))
		(make-instance 'short-form-method-combination
                               'name ',name
                               'order order
                               'documentation ',documentation
                               'operator ',operator
                               'identity-with-one-argument
                                 ',identity-with-one-argument))
            options)))


Example of Defining a Method Combination Type via Inheritance

;This example defines a method combination type that is similar
;to standard method combination, except that it also allows :or
;methods.  The :or methods are executed after the :before methods,
;before the :after methods, inside the :around methods, and before
;the primary method.  The primary method is only called if all the
;:or methods return nil; if any :or method returns non-nil, its
;value becomes the value of the generic function (or the value
;returned by call-next-method in the least specific :around method)
;in place of the values of the most specific primary method.

;This assumes approach 2 or 3 to making effective method code
;analyzable, and assumes one particular code analysis tool, whose
;details I will not try to explain here.
;Those assumptions are not critical.

;I'm assuming we don't want to try to extend the define-method-combination
;macro so that it could exploit inheritance.  Instead I will
;define the example directly in terms of the next layer down.

(defclass standard-method-combination-with-or
          (standard-method-combination)
          ())

(defmethod method-combination-object
           (generic-function
            (name (eql 'standard-with-or))
            options)
  (declare (ignore generic-function))
  (unless (null options)
    (error "standard-with-or method combination does not accept options"))
  (make-instance 'standard-method-combination-with-or))

;This uses call-next-method to get the effective method in the absence
;of any :or methods, then it modifies the effective method form to
;incorporate the :or methods in an OR special form wrapped around the
;call to the most specific primary method.
(defmethod compute-effective-method (generic-function
                                     methods
                                     (mc standard-method-combination-with-or))
  (let ((or-methods (remove '(:or) methods :key #'method-qualifiers
                            :test-not #'equal))
        (other-methods (remove '(:or) methods :key #'method-qualifiers
                               :test #'equal)))
    (lt:copyforms #'(lambda (subform kind usage)
                      (declare (ignore usage))
                      (if (and (listp kind) (listp subform)
                               (eq (first subform) 'method-call)
                               (null (method-qualifiers (second subform))))
                          ;; Put or methods before primary method 
                          (values `(or ,@(mapcar #'(lambda (method)
                                                     `(method-call ,method))
                                                 or-methods)
                                       ,subform)
                                  t)
                          ;; Leave all other subforms of effective method alone
                          subform))
                  (call-next-method generic-function other-methods mc))))     
\endscreen!



\endSubSection%{Expansion of define-method-combination}
\endSection%{Expanding the User Macros}

\beginSection{The Slot Parsing Protocol}

Standard classes store two distinct lists of slots.  The first is the
list of slots defined in the class proper.  The second is the total list
of slots the class has.  This includes inherited and locally defined
slots.  Both of these are available as lists of slot description objects.

As part of defining a class, the normalized slot specifications passed
to add-named-class must be converted to a list of slot description
objects.  The normalization is simply to ensure that the slot-name is
preceded in the list describing the slot by the keyword :name.

This conversion to slot description objects is done using the slot
parsing protocol.

The slot parsing protocol is quite simple.  It only contains only two
steps: a call to the generic function slot-description-class and a call
to make-instance.

Normalized slot-specifications are always parsed with respect to the
class they specify a slot for.  This allows the class the slot
description is being produced for to control the class of the slot
description object itself.  This slot-description-class generic function
is called with the class and the normalized slot specification to
determine the class of slot description which should be produced for the
class.

Once the appropriate class for the slot description has been determined,
the actual parsing is achieved by applying make-instance to the class and
the normalized slot specification.

This means that the legal set of slot option names for a given class of
slot-description is the same as the legal set of initarg names for that
class.  See lambda-list-congruence rules.
However, the macro that parses the defclass form is free to
use valid-slot-option-p to give earlier and better error messages.

\beginSubSection{slot-description-class}

The slot-description-class generic function..

\Defmeth {slot-description-class} {(class standard-class)
    normalized-slot-specification}

returns (symbol-class 'standard-slot-description)

\endSubSection{slot-description-class}


\endSection{The Slot Parsing Protocol}


\beginSection{compute-class-precedence-list}

This generic function computes the class precedence list of a class as described in Chapter 1.  The value is a list of class objects in order.


\Defmeth {compute-class-precedence-list} {(class standard-class)}

If in the computation of the class-precedence-list, the algorithm
runs across a class for which

(class-initialized-p class)=nil

an error is signalled.


\endSection%{compute-class-precedence-list}


\beginSection{The Slot Inheritance Protocol}

The total set of slots for any given class is computed by combining the
locally defined slots for the class and all of its superclasses.  For
standard classes, this combination proceeds according to the rules
described in chapter 1.  This combination is implemented by the
slot inheritance protocol.


The computation of the set of slots and their descriptions are
controlled at two levels.  The entire list is computed by
{\bf collect-slot-descriptions}.  It uses the subfunction
{\bf compute-effective-slot-description} to combine sets of slots-descriptions
that have the same slot-name.  

\beginsubsubsection{collect-slot-descriptions}

The generic function {\bf collect-slot-descriptions} collects an
ordered list of effective slot descriptions for this class.  It uses the class-direct-slots from each of the classes on (class-precedence-list class). 

\Defmeth {collect-slot-descriptions} {(class standard-class)} 

It sorts all the slots found into sets with the same name, ordered by
precedence according to the class precedence list.  It then calls
compute-effective-slotd to combine multiple definitions of a single slot.

\endsubsubsection%{collect-slot-descriptions}

\beginsubsubsection{compute-effective-slot-description}

\Defmeth {compute-effective-slot-description} 
   {(class standard-class) slot-description-list} 

The standard method for this generic function supports the inheritance
of slot options that is described in Chapter 1.  It returns a
slot-description object with a description computed from all the 
slot-descriptions in slot-description-list.

\endsubsubsection%{compute-effective-slot-description}


\beginsubsubsection{Example of specializing compute-effective-slot-description}

Suppose a user wanted to define a new metaclass which implemented a
different rule for the inheritance of the :type slot option.  This new
rule might want to say that a subclass must specify a type which is at
least as specific as the type specified by any of the superclasses.
If none of the superclasses specified a type, the local class may either
not specify a type at all or may specify any type it likes.

\screen!

(defmethod compute-effective-slot-description ((class my-class)
                                               slot-descriptions)
  (when (car slot-descriptions)
    (when (slot-boundp (car slot-descriptions) 'type)
      ;; The class has a local specification for this slot and
      ;; the :type option is specified in that specification.
      ;; Make sure the specified type is at least as specific
      ;; as all the other types specified.
      (let ((local-type (slot-value (car slot-descriptions) 'type)))
        (dolist (super-slot (cdr slot-descriptions))
          (when (slot-boundp super-slot 'type)
            (unless (subtypep slotd-type (slot-value super-slot 'type))
               (error "~S is not a subtype of ~S"
                      local-type 
                      (slot-value super-slot 'type))))))))
   (call-next-method))

\endscreen!

\endsubsubsection%{Example of Specializing compute-effective-slot-description}

\endSection%{The Slot Inheritance Protocol}

\beginSection{The Instance Structure Protocol}

Metaclasses determine the structure of their meta-instances.  This
includes allocating the memory for and managing the layout of the
instance.  This is handled by the instance structure protocol.

There are two level of description for access to instance structure.  At
the highest level, only slots are dealt with.  We call this Slot
Level Instance Access.  At the lower level, the user
has the ability to specify additional named storage to be allocated in an
instance.  This Access-key level is also the focus of optimization
for slot access, and hence for additional storage specified by the user.
All the methods at the Slot Level can be defined in terms of functions at the
Access-key level.

\beginSubSection{Slot Level Instance Access}

At the highest level, instance access is in terms of slots.  The basic
functions for accessing the slots of an instance are described in
chapters 1 and 2.  In this section we describe the generic functions
underlying those functions. The functions rely entirely on these generic
functions to implement their behavior.  Each of the corresponding
functions calls the generic functions directly, the only difference is
that the class of the object is included as the first argument to the
generic function.  In the case of setf functions, the class is the
second argument.  For example the slot-value and (setf slot-value)
functions are implemented in terms of slot-value-using-class and (setf slot-value-using-class) as follows: 

\screen!

(defun slot-value (instance slot-name)
  (slot-value-using-class (class-of instance) instance slot-name))

(defun (setf slot-value) (new-value instance slot-name)
  (setf (slot-value-using-class (class-of instance) instance slot-name)
        new-value))

\endscreen!

\beginsubsubsection{slot-value-using-class}

The generic function {\bf slot-value-using-class} is called by the
function {\bf slot-value}.

{\bf slot-value-using-class} returns the value of the slot with the
given name. All methods on slot-value-using-class call slot-missing if
the slot with the given name does not exist.  Some methods on
slot-value-using-class may do additional checks, for example to see if
the slot is bound.

\Defmeth {slot-value-using-class} {(class standard-class) instance slot-name}

Returns the value of the slot named slot-name if such a slot
exists and is bound.  If the slot does not exist calls slot-missing.  If
the slot exists but is not bound calls slot-unbound.

\Defmeth {slot-value-using-class} {(class structure-class) instance slot-name}

Returns the value of the slot named slot-name if such a slot
exists.  If the slot does not exists, it calls the generic function
slot-missing.

\endsubsubsection%{slot-value-using-class}

\beginsubsubsection{slot-boundp-using-class}

The generic function {\bf slot-boundp-using-class} is called by the
function {\bf slot-boundp}.

The generic function {\bf slot-boundp-using-class} tests whether a
specific slot in an instance of a given class is bound.  Not all
metaclasses support this operation.

\Defmeth {slot-boundp-using-class} {(class standard-class) instance slot-name}

If a slot with the given name exists, and that slot is bound, returns
true.  If a slot with the given name exists and that slot is not bound
returns false.  If no slot with the given name exists the function
slot-missing is called.

\Defmeth {slot-boundp-using-class} {(class structure-class) instance slot-name}

If a slot with the given name exists, it returns true.  If no slot with the
given name exists the function slot-missing is called.

\endsubsubsection%{slot-boundp-using-class}

\beginsubsubsection{slot-makunbound-using-class}

The generic function {\bf slot-makunbound-using-class}
is called by the function {\bf slot-makunbound}.

For metaclass which support unbound slots, the generic function {\bf
slot-makunbound-using-class} restores a slot to its unbound state.
Attempting to read a slot after it has been made unbound will result in
a call to {\bf slot-unbound}.

\Defmeth {slot-makunbound-using-class} {(class standard-class) instance slot-name}

If a slot with the given name exists in the class the slot is restored
to its original unbound state.  If there is no slot with the given name
in the class calls slot-missing.

\Defmeth {slot-makunbound-using-class} {(class structure-class) instance slot-name}

Since this operation is not supported by structure-class, this method
signals an error.

\endsubsubsection%{slot-makunbound-using-class}

\beginsubsubsection{slot-exists-p-using-class}

The generic function {\bf slot-exists-p-using-class} is called by the
function {\bf slot-exists-p}.

The generic function {\bf slot-exists-p-using-class} tests whether a
slot by the given exists in the instance.

\Defmeth {slot-exists-p-using-class} {(class standard-class) instance slot-name}

If either a :instance or :class slot slot with the given name exists in
the class returns true.  Otherwise returns false.

\Defmeth {slot-exists-p-using-class} {(class structure-class) instance slot-name}

If a slot with the given name exists in the class returns true.
Otherwise returns false.

\endsubsubsection{slot-exists-p-using-class}

\endSubSection%{Slot Level Instance Access}

\beginSubSection{Access-Key Instance Access}

At the Access-Key level, there is direct access to instances
of metatype standard-class.  However, even at this level, instances 
are accessed through a symbolic mapping.   It is just that the set of
keys used for accessing the objects can be computed by a method on the
class.  Optimized access through those keys is supported.  Thus, a
user can think of a Loops class having a set of slots, and a set of
properties on those slots.  At the lower level, the class might
generate a separate access key for a property list for each slot. 

Note that even with this protocol, the user cannot portably change the
mechanisms for laying out storage, nor for class-of.  There may be reasonable
semi-portable ways of doing these, but CLOS does not not specify
how to do this.

\beginsubsubsection{compute-class-access-keys}

The purpose of the generic function {\bf compute-class-access-keys}
is to compute the entire set of access keys that will be used with
an instance of standard-class.  This generic function is called by the
update-dependent method on standard-class, and its value is cached
in an implementation dependent way with the class.  The function
{\bf class-access-keys} can retrieve the latest value stored.

\Defmeth {compute-class-access-keys} {(class standard-class)}

This method returns two values, each of which must be a list of access-keys.
No  access-key can appear more than once in a list, and the two lists may have
no elements in common. The first value is the set of access keys for which
storage will be allocated in the instance.  The second is a list of
access-keys for which storage will be allocated in the class.
All these access-keys will be usable by standard-instance-access to fetch
the contents of the storage.

Storage associated with keys in the second list will also be accesible
through the function standard-class-access.

Specific implementations may extend the meaning of the access-key
to provide a means to describe data packing and garbage collection
control.


\endsubsubsection%{compute-class-access-keys}


\beginsubsubsection{class-access-keys}

The storage that is allocated for any instance is determined by
a set of access keys computed by compute-class-access-keys.   
The latest values stored away by update-dependent can be obtained by
this function.


Returns two values, a list of instance-keys and a list of class-keys.

The first will be accessible by standard-instance-access,
and the second through standard-class-access.
    
   
\endsubsubsection%{class-access-keys}


\beginsubsubsection{allocate-standard-instance}

Allocate-standard-instance is a function that takes an instance of
standard-class as an argument.  It uses information cached in the class
by update-dependent to create a structure that has enough room
for one entry for each access-key on the list of instanceaccess keys. 

(defun allocate-standard-instance (class)
  ;; implementation dependent code for allocation
  ) 
   

\endsubsubsection%{allocate-standard-instance}

\beginsubsubsection{standard-instance-access}

The function {\bf standard-instance-access} is the low level access
primitive for instances in CLOS.

\screen!
(defun standard-instance-access (instance access-key)
  ;;instance must be of metatype standard-instance
  ;;return value from instance, and condition-code
  )
\endscreen! 

The first value returned by standard-instance-access is the value in
storage if there is one.  The second value is a condition-code, one of
:value, :unbound, :missing.

Thus, some model code for slot-value-using-class for standard-class is:

\screen!
(defmethod slot-value-using-class ((class standard-class) object slot-name)
  (multiple-value-bind (value condition)
                       (standard-instance-access object slot-name)
    (ecase condition
      (:value value)
      (:missing (slot-missing class object slot-name 'slot-value))
      (:unbound (slot-unbound class object slot-name))))
\endscreen! 

The code for the other slot level methods for standard-class are coded
similarly.

\endSubSection%{Access-Key Instance Access}


\beginSubSection{Optimized Symbolic Level Instance Access}

The standard-instance-access function provides the basic interface to
the implementation-specific standard instance access optimization.
In order to support the optimization there is a contract between
standard-instance-access and the kernel methods which provide the class
updating protocol.  Specifically, standard-instance-access is allowed to
assume that the set of access-keys does not change unless update-dependent
has been called, and it is the responsibility of update-dependent
to inform each of the effected methods about how to update themselves.

In order to allow flexible use of the optimization
standard-instance-access provides, there is a mechanism for deoptimizing
calls to standard-instance-access for a particular class.  This
mechanism causes all the calls to standard-instance-access for a
particular class to call the trap function instead.  The trap function
received the instance and the description as its arguments.

\Defun {deoptimize-standard-instance-access} {class}
...


\endSubSection%{Optimized Symbolic Level Instance Access}


\endSection%{The Instance Structure Protocol}


\beginSection{The Instance Access Optimization Protocol}

As described in chapters 1 and 2, most code access instances at the slot
level.  But, as described in the Instance Structure Protocol section,
a call to slot-value results in a call to the slot-value-using-class
generic function which then calls standard-instance-access.  If every
call to slot-value had to do this generic function call, slot access
would be too slow.

To solve this problem, CLOS provides a mechanism for optimizing calls to
slot-value.  At compile-time, this mechanism optimizes calls to
slot-value where it is possible to convert the call to a use of
standard-instance-access.  This requires that the compiler be able to
ascertain the class of an instance (it can be a subclass of that class
at run-time).

This mechanism is general enough that it can be used to optimize any
access to instances whose class is known at compile time. 

{\it
There is a notion which needs to be defined here in a protable way.
It is the concept of a context in which a call to standard-instance-access
can be optimized.
 }

The fundamental hook for this mechanism is the optimize-instance-access
generic function.  This generic function is called on any instance
accessing form which, if it were converted to a call to
standard-instance-access could be further optimized.  This gives the
metaclass programmer an opportunity to optimize any instance accessing
form into a call to standard-instance-access whenever it would do any
good.

optimize-instance-access receives as arguments the class of the instance
being accessed (or a superclass) the function being called on the
instance, all the arguments to the function, the particular one of those
arguments which will be the instance at run-time and information about
the context the access is in.  The context will be the symbol :effect if
the compiler is guaranteeing that this access is for effect only.

When a metaclass optimizes slot accesses, it may do so in a way that
makes them deoptimizable.  A deoptimized slot access is one that goes
through the full access protocol rather than the optimized access.  If a
metaclass can deoptimize its slot accesses, it should return true from 
can-deoptimize-slot-accesses-p, if not it should return false.

\Defmeth {can-deoptimize-slot-accesses-p} {(class standard-class)}

Returns true.

\Defmeth {can-deoptimize-slot-accesses-p} {(class structure-class)}

Returns false.

\Defmeth {deoptimize-slot-accesses} {(class standard-class)}

Deoptimizes its optimized slot accesses by calling
deoptimize-standard-instance-access.

\Defmeth {can-deoptimize-slot-accesses-p} {(class structure-class)}

Signals an error.

\endSection%{The Instance Access Optimization Protocol}


\beginSection{The Method Lookup Protocol}

When a generic function is called with particular arguments, it must
determine the code to execute.  This code is called the {\bit effective
method\/} for those arguments.  The effective method is a {\bit
combination\/} of the applicable methods in the generic function.  A
combination of methods is a Lisp expression that contains calls to some
or all of the methods.  If a generic function is called and no methods
apply, the generic function {\bf no-applicable-method} is invoked.

When the effective method has been determined, it is converted to
an actual function and the actual function is applied to the same
arguments as were passed to the generic function. Whatever values it
returns are returned as the values of the generic function.

The specification for the precise way the kernel computes the effective
method appears in chapter 1.  This section describes the protocol used
to compute and invoke the effective method.

The key component in this protocol is the discriminator code for the
generic function.  The discriminator code for a generic function is
called whenever the generic function is called; it computes the
effective method and invokes it.  The discriminator code for a generic
function is computed each time the generic function changes.  When the
generic function itself is called, the pre-computed discriminator code
is called.  The protocol described here is used to compute the
discriminator code, thus the protocol described here is not invoked when
the generic function is called, it is invoked whenever the generic
function is updated.  This allows method lookup to be a fast operation.

The standard-method on update-generic-function calls
compute-discriminator-code whenever the generic function changes.
compute-discriminator-code is expected to return the discriminator code
for the generic function.  This discriminator code must be valid until
the next time update-generic-function is called.

The standard-method on compute-discriminator-code provides the
documented behavior of computing the effective method and calling it.
It does this by providing a second layer of protocol, specifically the
compute-effective-method generic function.  compute-effective-method is
called by the standard-method on compute-discriminator-code to compute
the effective method for a set of applicable methods.

There are also several support functions supplied by the kernel to
assist users in extending the method lookup protocol.  These support
functions implement certain key parts of the kernel method lookup
behavior.


\Defgen {compute-discriminator-code} {generic-function}

\Defmeth {compute-discriminator-code} {(generic-function standard-generic-function)}

\screen!

(defmethod compute-discriminator-code 
           ((generic-function standard-generic-function))
  #'(lambda (&rest args)
      (let* ((lambda-list (slot-value generic-function 'lambda-list))
             (methods (compute-applicable-methods generic-function args))
             (function
               (make-effective-method-function
                  generic-function
                  (compute-effective-method
                    generic-function
                    methods
                    (slot-value generic-function
                                'method-combination-type)
                    (slot-value generic-function
                                'method-combination-arguments)))))
        (check-keyword-arguments lambda-list methods args)
        (apply function args))))


\endscreen!

\Defgen {compute-effective-method} {generic-function applicable-methods
method-combination-type method-combination-arguments}

\Defmeth {compute-effective-method} {(generic-function standard-generic-function) applicable-methods method-combination-type method-combination-arguments}

{\it Actually, there is one method here for each pre-defined
method-combination-type.  This needs to be explained in terms how
define-method-combination expands into a defmethod for
compute-effective-method.
 }

\beginSubSection{Support Functions for Method Lookup}

In order to help the user use the method lookup protocol the CLOS kernel
provides some helpful support functions.

\Defun {compute-applicable-methods} {generic-function arguments}

Given a generic function and a set of arguments, this uses the standard
rules to determine the ordered set of applicable methods.

\Defun {compute-combination-points} {generic-function}

Computes all the combination points for this generic functions.  That is
all the points at which (if you are using combined-methods) methods must
be combined.  For each point it also provides the ordered set of
methods applicable at the point.

{\it This may sound like it is too implementation specific to be useful
in the metaobject protocol, but I think that is because of the way I am
describing it.  I believe a lot of method lookup hackers are going to
want to compute this, and given that it is hard to compute accurately
and quickly I think we should provide it.
 }

\Defun {check-keyword-arguments} {generic-function lambda-list methods args} 

This implements the keyword congruence rules specified in chapter 1.  If
the keyword arguments in args are OK, this returns t.  Otherwise it
signals an error. 

\Defun {make-method-call} {method-list \key operator identity-with-one-argument}

This is documented in chapter 2.

\Defun {make-function-call} {function}

This has behavior similar to make-method-call.  It produces a call to
the function with all the arguments of the generic function.

{\it we should invent a better name for this. }

\Defun {make-effective-method-function} {generic-function effective-method-body}

This takes the effective method body as computed by
compute-effective-method-body and converts it to a function which
implements the effective method.  This function accepts the same
arguments the generic function accepts.  This function does the standard
keyword congruence checking.  This function arranges to call all the
methods ``as if with :allow-other-keys t''.

{\it Basically, make-effective-method-function, make-method-call and
make-function-call are the ones that have the contract that makes
calling methods work.  They communicate the information about what
parameters the arguments will be bound to, how to hack :allow-other-keys
t etc. }

{\it I am concerned that actually we have to get rid of make-method-call
and have a call-method special form.  Otherwise, I don't know how
someone is going to build a portable stepper for standard generic
functions.
 }

\endSubSection%{Support Functions for Method Lookup}

\beginSubSection{Example of using the Method Lookup Protocol}

This example defines a special class of tracing generic function.  This
class of generic function provides two kinds of tracing facilities.  The
first kind allows the user to specify that calls to particular generic
functions should cause breakpoints.  The second allows the user to
specify that calls to the effective method for particular sets of
methods should cause breakpoints.

\screen!

(defvar *trace-generic-functions* ())
(defvar *trace-effective-methods* ())

(defclass tracing-generic-function (standard-generic-function) ())

(defmethod compute-discriminator-code ((gf tracing-generic-function))
  (let ((real-discriminator-code (call-next-method)))
    #'(lambda (&rest args)
        (when (member gf *trace-generic-functions*)
          (break "The generic function ~S is one of the generic~%~
                  functions on *trace-generic-functions*"
                 gf))
        (apply real-discriminator-code args))))

(defmethod compute-effective-method ((gf tracing-generic-function)
                                     methods
                                     method-combination-type
                                     method-combination-arguments)  
  `(progn
     (when (member ',methods *trace-effective-methods* :test #'equal)
       (break "The set of methods ~S is one of the sets of~%~
               methods on *trace-effective-methods*."
              ',methods))
     ,(call-next-method)))

\endscreen!

\endSubSection%{Example of using the Method Lookup Protocol}

\endSection%{The Method Lookup Protocol}

\endChapter
\bye