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

Compiling make-instance when using metaclasses and qualified methods on make-instance



In CLOS on the Symbolics (8.1.1), this fails.  Symbolics admits the
possibility of failure without holding out a possibility of repair.  I put a
quick patch together to "fix" this error, but I am insecure regarding the
possible effects of the patch.

Below is the problem description, the patch, and Symbolic's response.

If anyone has suggestions about the patch or the problem or the possibility
that they may need a similar capability, I would appreciate knowing it.


The problem seems to boil down to a problem with the compilation of
(make-instance 'class-name) forms.   Normally, make-instance will resolve
calls of this form by doing something similar to 
(make-instance (find-class 'class-name)).

In our system where we are using a subclass of standard-class as the default
metaclass for new object classes AND we have wrapped make-instance for instances
of that metaclass with an :around method to handle some initializations,
the compiler apparently fails to account for "(find-class 'class-name)" above
returning anything but an instance of standard-class.

The example below illustrates the problem.
Compile it and load it to note the internal error reported.

(eval-when (compile load eval)
  (defclass new-class (standard-class)
      ((instances
         :allocation :instance
         :accessor instances-of
         :initform nil))))

(defclass new-object ()
    ()
  (:metaclass new-class))

(defmethod make-instance :around ((class new-class)
                                  &key &allow-other-keys)
  (let ((instance (call-next-method)))
    (pushnew instance (instances-of class))
    instance))

(defclass test-object ()
    ()
  (:metaclass new-class))

(setf a-test-object (make-instance 'test-object))


;;; -*- Mode: LISP; Syntax: Common-Lisp; Base: 10; Package: CLOS-INTERNALS -*-
1;;; DHM 30-Oct-91 Don't compain if generic function is make-instance (because
;;;               that does not interpose between the functions of concern).

0(si:allow-redefinition 'VERIFY-FAST-P)
;;; Complain if FAST-P is true and something other than calling a system method occurs between
;;; the system method for ALLOCATE-INSTANCE and the system method for SHARED-INITIALIZE
(DEFUN VERIFY-FAST-P (GENERIC-FUNCTION PRIMARY-CALLED FAST-P FORM)
  (WHEN (AND FAST-P
	     (COND ((EQ GENERIC-FUNCTION *ALLOCATE-INSTANCE*) PRIMARY-CALLED)	     ;after
		   ((EQ GENERIC-FUNCTION *SHARED-INITIALIZE*) (NOT PRIMARY-CALLED))  ;before
		   ((EQ GENERIC-FUNCTION *INITIALIZE-INSTANCE*) (NOT PRIMARY-CALLED));before
		   ((eq GENERIC-FUNCTION *make-instance*) nil)
		   (T T)))
    (ERROR "INTERNAL ERROR: FAST-P true but ~S occurred unexpectedly" FORM)))


Date: Thu, 31 Oct 1991 14:07 CST
From: Mark Nahabedian <naha@YUKON.SCRC.Symbolics>
Subject: compiling make-instance while using metaclasses in clos
To: dmitchell@trc, customer-reports@STONY-BROOK.SCRC.Symbolics
In-Reply-To: <19911030195123.4.DON@SHAKTI.trc.amoco.com>,
             <19911030230926.8.DON@SHAKTI.trc.amoco.com>

Symbolics currently does not support the full metaobject protocol nor,
as far as I am aware, do other Lisp vendors.  The only part of the
metaobject protocol currently supported is that concerning
introspection, operations for examining classes and generic functions,
like CLASS-DIRECT-SUPERCLASSES and GENERIC-FUNCTION-METHODS.  We do not
support specialization of class metaobjects, the feature you are
attempting to use.

Symbolics' goal in further Lisp language development is to track the
emerging ANSI standard currently being drafted by the X3J13 CommonLisp
standardization committee.  At this time, the committee has chosen not
to include the metaobject protocol in the specification.  The committee
might reconsider if there is sufficient demand for the metaobject
protocol once the specification is submitted for public review.  Also
note that the metaobject protocol as it now stands has not undergone
much scrutiny from the lisp implementation community.  Parts of it might
very well change before it were incorporated into a standard.

In your example, you are trying to define classes which record every
instance of them which were ever created.  Here is a possible workaround
which does not require the metaobject protocol.  This approach will be
more difficult to use depending on what use you will be making of the
recorded instances, but it is supported.

Define a class which you mix into classes whose instances you want to
record.  You can then specialize CLOS:ALLOCATE-INSTANCE for this mixin
class (probably an after method would be most suitable here) to record
each instance when it is created.

Since you won't have a slot in the class object in which to record the
instances as they are created, you must put them somewhere else.  Either
an ALIST or a hash table which maps class objects to a list of instances
would serve this purpose.

I appologize for the inconvenience this approach entails.  Rest assured,
you are not alone in your desire to utilize the metaobject protocol.
Perhaps some day it will be widely available.
-------------------- end included message --------------------

Don Mitchell			dmitchell@trc.amoco.com
Amoco Production Company	(918) 660-4270
Tulsa Research Center
P.O. Box 3385, Tulsa, OK 74102