/[cmucl]/src/pcl/std-class.lisp
ViewVC logotype

Contents of /src/pcl/std-class.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Sat Oct 19 17:23:31 1991 UTC (22 years, 6 months ago) by ram
Branch: MAIN
Changes since 1.1: +41 -36 lines
Merged with latest PCL version.
1 wlott 1.1 ;;;-*-Mode:LISP; Package:PCL; Base:10; Syntax:Common-lisp -*-
2     ;;;
3     ;;; *************************************************************************
4     ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
5     ;;; All rights reserved.
6     ;;;
7     ;;; Use and copying of this software and preparation of derivative works
8     ;;; based upon this software are permitted. Any distribution of this
9     ;;; software or derivative works must comply with all applicable United
10     ;;; States export control laws.
11     ;;;
12     ;;; This software is made available AS IS, and Xerox Corporation makes no
13     ;;; warranty about the software, its performance or its conformity to any
14     ;;; specification.
15     ;;;
16     ;;; Any person obtaining a copy of this software is requested to send their
17     ;;; name and post office or electronic mail address to:
18     ;;; CommonLoops Coordinator
19     ;;; Xerox PARC
20     ;;; 3333 Coyote Hill Rd.
21     ;;; Palo Alto, CA 94304
22     ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
23     ;;;
24     ;;; Suggestions, comments and requests for improvements are also welcome.
25     ;;; *************************************************************************
26     ;;;
27    
28     (in-package 'pcl)
29    
30     (define-gf-predicate classp class)
31     (define-gf-predicate standard-class-p standard-class)
32     (define-gf-predicate forward-referenced-class-p forward-referenced-class)
33    
34    
35    
36     (defmethod shared-initialize :after ((object documentation-mixin)
37     slot-names
38     &key documentation)
39     (declare (ignore slot-names))
40     (setf (plist-value object 'documentation) documentation))
41    
42    
43     (defmethod documentation (object &optional doc-type)
44     (lisp:documentation object doc-type))
45    
46     (defmethod (setf documentation) (new-value object &optional doc-type)
47     (declare (ignore new-value doc-type))
48     (error "Can't change the documentation of ~S." object))
49    
50    
51     (defmethod documentation ((object documentation-mixin) &optional doc-type)
52     (declare (ignore doc-type))
53     (plist-value object 'documentation))
54    
55     (defmethod (setf documentation) (new-value (object documentation-mixin) &optional doc-type)
56     (declare (ignore doc-type))
57     (setf (plist-value object 'documentation) new-value))
58    
59    
60     (defmethod documentation ((slotd standard-slot-definition) &optional doc-type)
61     (declare (ignore doc-type))
62     (slot-value slotd 'documentation))
63    
64     (defmethod (setf documentation) (new-value (slotd standard-slot-definition) &optional doc-type)
65     (declare (ignore doc-type))
66     (setf (slot-value slotd 'documentation) new-value))
67    
68    
69     ;;;
70     ;;; Various class accessors that are a little more complicated than can be
71     ;;; done with automatically generated reader methods.
72     ;;;
73     (defmethod class-wrapper ((class pcl-class))
74     (with-slots (wrapper) class
75     (let ((w? wrapper))
76     (if (consp w?)
77     (let ((new (make-wrapper class)))
78     (setf (wrapper-instance-slots-layout new) (car w?)
79     (wrapper-class-slots new) (cdr w?))
80     (setq wrapper new))
81     w?))))
82    
83     (defmethod class-precedence-list ((class pcl-class))
84     (unless (class-finalized-p class) (finalize-inheritance class))
85     (with-slots (class-precedence-list) class class-precedence-list))
86    
87     (defmethod class-finalized-p ((class pcl-class))
88     (with-slots (wrapper) class (not (null wrapper))))
89    
90     (defmethod class-prototype ((class std-class))
91     (with-slots (prototype) class
92     (or prototype (setq prototype (allocate-instance class)))))
93    
94     (defmethod class-direct-default-initargs ((class std-class))
95     (plist-value class 'direct-default-initargs))
96    
97     (defmethod class-default-initargs ((class std-class))
98     (plist-value class 'default-initargs))
99    
100     (defmethod class-constructors ((class std-class))
101     (plist-value class 'constructors))
102    
103     (defmethod class-slot-cells ((class std-class))
104     (plist-value class 'class-slot-cells))
105    
106    
107     ;;;
108     ;;; Class accessors that are even a little bit more complicated than those
109     ;;; above. These have a protocol for updating them, we must implement that
110     ;;; protocol.
111     ;;;
112    
113     ;;;
114     ;;; Maintaining the direct subclasses backpointers. The update methods are
115     ;;; here, the values are read by an automatically generated reader method.
116     ;;;
117     (defmethod add-direct-subclass ((class class) (subclass class))
118     (with-slots (direct-subclasses) class
119     (pushnew subclass direct-subclasses)
120     subclass))
121    
122     (defmethod remove-direct-subclass ((class class) (subclass class))
123     (with-slots (direct-subclasses) class
124     (setq direct-subclasses (remove subclass direct-subclasses))
125     subclass))
126    
127     ;;;
128     ;;; Maintaining the direct-methods and direct-generic-functions backpointers.
129     ;;;
130     ;;; There are four generic functions involved, each has one method for the
131     ;;; class case and another method for the damned EQL specializers. All of
132     ;;; these are specified methods and appear in their specified place in the
133     ;;; class graph.
134     ;;;
135     ;;; ADD-METHOD-ON-SPECIALIZER
136     ;;; REMOVE-METHOD-ON-SPECIALIZER
137     ;;; SPECIALIZER-METHODS
138     ;;; SPECIALIZER-GENERIC-FUNCTIONS
139     ;;;
140     ;;; In each case, we maintain one value which is a cons. The car is the list
141     ;;; methods. The cdr is a list of the generic functions. The cdr is always
142     ;;; computed lazily.
143     ;;;
144    
145     (defmethod add-method-on-specializer ((method method) (specializer class))
146     (with-slots (direct-methods) specializer
147     (setf (car direct-methods) (adjoin method (car direct-methods)) ;PUSH
148     (cdr direct-methods) ()))
149     method)
150    
151     (defmethod remove-method-on-specializer ((method method) (specializer class))
152     (with-slots (direct-methods) specializer
153     (setf (car direct-methods) (remove method (car direct-methods))
154     (cdr direct-methods) ()))
155     method)
156    
157     (defmethod specializer-methods ((specializer class))
158     (with-slots (direct-methods) specializer
159     (car direct-methods)))
160    
161     (defmethod specializer-generic-functions ((specializer class))
162     (with-slots (direct-methods) specializer
163     (or (cdr direct-methods)
164     (setf (cdr direct-methods)
165     (gathering1 (collecting-once)
166     (dolist (m (car direct-methods))
167     (gather1 (method-generic-function m))))))))
168    
169    
170    
171     ;;;
172     ;;; This hash table is used to store the direct methods and direct generic
173     ;;; functions of EQL specializers. Each value in the table is the cons.
174     ;;;
175 ram 1.2 (defvar *specializer-with-object-methods* (make-hash-table :test #'eql))
176 wlott 1.1
177 ram 1.2 (defmethod add-method-on-specializer ((method method) (specializer specializer-with-object))
178     (let* ((object (specializer-object specializer))
179     (entry (gethash object *specializer-with-object-methods*)))
180 wlott 1.1 (unless entry
181     (setq entry
182 ram 1.2 (setf (gethash object *specializer-with-object-methods*)
183 wlott 1.1 (cons nil nil))))
184     (setf (car entry) (adjoin method (car entry))
185     (cdr entry) ())
186     method))
187    
188 ram 1.2 (defmethod remove-method-on-specializer ((method method) (specializer specializer-with-object))
189     (let* ((object (specializer-object specializer))
190     (entry (gethash object *specializer-with-object-methods*)))
191 wlott 1.1 (when entry
192     (setf (car entry) (remove method (car entry))
193     (cdr entry) ()))
194     method))
195    
196 ram 1.2 (defmethod specializer-methods ((specializer specializer-with-object))
197     (car (gethash (specializer-object specializer) *specializer-with-object-methods*)))
198 wlott 1.1
199 ram 1.2 (defmethod specializer-generic-functions ((specializer specializer-with-object))
200     (let* ((object (specializer-object specializer))
201     (entry (gethash object *specializer-with-object-methods*)))
202 wlott 1.1 (when entry
203     (or (cdr entry)
204     (setf (cdr entry)
205     (gathering1 (collecting-once)
206     (dolist (m (car entry))
207     (gather1 (method-generic-function m)))))))))
208    
209    
210    
211     (defun real-load-defclass (name metaclass-name supers slots other accessors)
212     (do-standard-defsetfs-for-defclass accessors) ;***
213     (apply #'ensure-class name :metaclass metaclass-name
214     :direct-superclasses supers
215     :direct-slots slots
216     :definition-source `((defclass ,name)
217     ,(load-truename))
218     other))
219    
220     (defun ensure-class (name &rest all)
221     (apply #'ensure-class-using-class name (find-class name nil) all))
222    
223     (defmethod ensure-class-using-class (name (class null) &rest args &key)
224     (multiple-value-bind (meta initargs)
225     (ensure-class-values class args)
226     (setf class (apply #'make-instance meta :name name initargs)
227     (find-class name) class)
228     (inform-type-system-about-class class name) ;***
229     class))
230    
231     (defmethod ensure-class-using-class (name (class pcl-class) &rest args &key)
232     (multiple-value-bind (meta initargs)
233     (ensure-class-values class args)
234     (unless (eq (class-of class) meta) (change-class class meta))
235     (apply #'reinitialize-instance class initargs)
236     (inform-type-system-about-class class name) ;***
237     class))
238    
239     (defun ensure-class-values (class args)
240     (let* ((initargs (copy-list args))
241     (unsupplied (list 1))
242     (supplied-meta (getf initargs :metaclass unsupplied))
243     (supplied-supers (getf initargs :direct-superclasses unsupplied))
244     (supplied-slots (getf initargs :direct-slots unsupplied))
245     (meta
246     (cond ((neq supplied-meta unsupplied)
247     (find-class supplied-meta))
248     ((or (null class)
249     (forward-referenced-class-p class))
250     *the-class-standard-class*)
251     (t
252     (class-of class))))
253     (proto (class-prototype meta)))
254     (flet ((fix-super (s)
255     (cond ((classp s) s)
256     ((not (legal-class-name-p s))
257     (error "~S is not a class or a legal class name." s))
258     (t
259     (or (find-class s nil)
260     (setf (find-class s)
261     (make-instance 'forward-referenced-class
262     :name s)))))))
263     (loop (unless (remf initargs :metaclass) (return)))
264     (loop (unless (remf initargs :direct-superclasses) (return)))
265     (loop (unless (remf initargs :direct-slots) (return)))
266     (values meta
267     (list* :direct-superclasses
268     (and (neq supplied-supers unsupplied)
269     (mapcar #'fix-super supplied-supers))
270     :direct-slots
271     (and (neq supplied-slots unsupplied) supplied-slots)
272     initargs)))))
273    
274    
275     ;;;
276     ;;;
277     ;;;
278     (defmethod shared-initialize :before ((class std-class)
279     slot-names
280     &key direct-superclasses)
281     (declare (ignore slot-names))
282     ;; *** error checking
283     )
284    
285     (defmethod shared-initialize :after
286     ((class std-class)
287     slot-names
288 ram 1.2 &key (direct-superclasses nil direct-superclasses-p)
289     (direct-slots nil direct-slots-p)
290     (direct-default-initargs nil direct-default-initargs-p))
291 wlott 1.1 (declare (ignore slot-names))
292 ram 1.2 (setq direct-superclasses
293     (if direct-superclasses-p
294     (setf (slot-value class 'direct-superclasses)
295     (or direct-superclasses
296     (list *the-class-standard-object*)))
297     (slot-value class 'direct-superclasses)))
298     (setq direct-slots
299     (if direct-slots-p
300     (setf (slot-value class 'direct-slots)
301     (mapcar #'(lambda (pl) (make-direct-slotd class pl)) direct-slots))
302     (slot-value class 'direct-slots)))
303     (if direct-default-initargs-p
304     (setf (plist-value class 'direct-default-initargs) direct-default-initargs)
305     (setq direct-default-initargs (plist-value class 'direct-default-initargs)))
306 wlott 1.1 (setf (plist-value class 'class-slot-cells)
307     (gathering1 (collecting)
308     (dolist (dslotd direct-slots)
309     (when (eq (slotd-allocation dslotd) class)
310     (let ((initfunction (slotd-initfunction dslotd)))
311     (gather1 (cons (slotd-name dslotd)
312     (if initfunction (funcall initfunction) *slot-unbound*))))))))
313     (add-direct-subclasses class direct-superclasses)
314     (add-slot-accessors class direct-slots))
315    
316     (defmethod reinitialize-instance :before ((class std-class)
317     &key direct-superclasses
318     direct-slots
319     direct-default-initargs)
320     (declare (ignore direct-default-initargs))
321 ram 1.2 (remove-direct-subclasses class (class-direct-superclasses class))
322 wlott 1.1 (remove-slot-accessors class (class-direct-slots class)))
323    
324     (defmethod reinitialize-instance :after ((class std-class)
325     &rest initargs
326     &key)
327     (update-class class nil)
328     (map-dependents class
329     #'(lambda (dependent)
330     (apply #'update-dependent class dependent initargs))))
331    
332     (defun add-slot-accessors (class dslotds)
333     (fix-slot-accessors class dslotds 'add))
334    
335     (defun remove-slot-accessors (class dslotds)
336     (fix-slot-accessors class dslotds 'remove))
337    
338     (defun fix-slot-accessors (class dslotds add/remove)
339     (flet ((fix (gfspec name r/w)
340     (let ((gf (ensure-generic-function gfspec)))
341     (case r/w
342     (r (if (eq add/remove 'add)
343     (add-reader-method class gf name)
344     (remove-reader-method class gf)))
345     (w (if (eq add/remove 'add)
346     (add-writer-method class gf name)
347     (remove-writer-method class gf)))))))
348     (dolist (dslotd dslotds)
349     (let ((slot-name (slotd-name dslotd)))
350     (dolist (r (slotd-readers dslotd)) (fix r slot-name 'r))
351     (dolist (w (slotd-writers dslotd)) (fix w slot-name 'w))))))
352    
353    
354     (defun add-direct-subclasses (class new)
355     (dolist (n new)
356     (unless (memq class (class-direct-subclasses class))
357     (add-direct-subclass n class))))
358    
359     (defun remove-direct-subclasses (class new)
360     (let ((old (class-direct-superclasses class)))
361     (dolist (o (set-difference old new))
362     (remove-direct-subclass o class))))
363    
364    
365     ;;;
366     ;;;
367     ;;;
368     (defmethod finalize-inheritance ((class std-class))
369     (update-class class t))
370    
371    
372     ;;;
373     ;;; Called by :after reinitialize instance whenever a class is reinitialized.
374     ;;; The class may or may not be finalized.
375     ;;;
376     (defun update-class (class finalizep)
377     (when (or finalizep (class-finalized-p class))
378     (let* ((dsupers (class-direct-superclasses class))
379     (dslotds (class-direct-slots class))
380     (dinits (class-direct-default-initargs class))
381     (cpl (compute-class-precedence-list class dsupers))
382     (eslotds (compute-slots class cpl dslotds))
383     (inits (compute-default-initargs class cpl dinits)))
384    
385     (update-cpl class cpl)
386     (update-slots class cpl eslotds)
387     (update-inits class inits)
388     (update-constructors class)))
389     (unless finalizep
390     (dolist (sub (class-direct-subclasses class)) (update-class sub nil))))
391    
392     (defun update-cpl (class cpl)
393     (when (class-finalized-p class)
394     (unless (equal (class-precedence-list class) cpl)
395     (force-cache-flushes class)))
396     (setf (slot-value class 'class-precedence-list) cpl))
397    
398     (defun update-slots (class cpl eslotds)
399     (multiple-value-bind (nlayout nwrapper-class-slots)
400     (compute-storage-info cpl eslotds)
401     ;;
402     ;; If there is a change in the shape of the instances then the
403     ;; old class is now obsolete.
404     ;;
405     (let* ((owrapper (class-wrapper class))
406     (olayout (and owrapper (wrapper-instance-slots-layout owrapper)))
407     (owrapper-class-slots (and owrapper (wrapper-class-slots owrapper)))
408     (nwrapper
409     (cond ((null owrapper)
410     (make-wrapper class))
411     ((and (equal nlayout olayout)
412     (not
413     (iterate ((o (list-elements owrapper-class-slots))
414     (n (list-elements nwrapper-class-slots)))
415     (unless (eq (car o) (car n)) (return t)))))
416     owrapper)
417     (t
418     ;;
419     ;; This will initialize the new wrapper to have the same
420     ;; state as the old wrapper. We will then have to change
421     ;; that. This may seem like wasted work (it is), but the
422     ;; spec requires that we call make-instances-obsolete.
423     ;;
424     (make-instances-obsolete class)
425     (class-wrapper class)))))
426     (with-slots (wrapper no-of-instance-slots slots) class
427     (setf no-of-instance-slots (length nlayout)
428     slots eslotds
429     (wrapper-instance-slots-layout nwrapper) nlayout
430     (wrapper-class-slots nwrapper) nwrapper-class-slots
431 ram 1.2 wrapper nwrapper))
432     (dolist (eslotd eslotds)
433     (when (typep eslotd 'standard-effective-slot-definition)
434     (setf (slotd-class eslotd) class)
435     (setf (slotd-instance-index eslotd)
436     (instance-slot-index nwrapper (slotd-name eslotd))))))))
437 wlott 1.1
438     (defun compute-storage-info (cpl eslotds)
439     (let ((instance ())
440     (class ()))
441     (dolist (eslotd eslotds)
442     (let ((alloc (slotd-allocation eslotd)))
443     (cond ((eq alloc :instance) (push eslotd instance))
444     ((classp alloc) (push eslotd class)))))
445     (values (compute-layout cpl instance)
446     (compute-class-slots class))))
447    
448     (defun compute-layout (cpl instance-eslotds)
449     (let* ((names
450     (gathering1 (collecting)
451     (dolist (eslotd instance-eslotds)
452     (when (eq (slotd-allocation eslotd) :instance)
453     (gather1 (slotd-name eslotd))))))
454     (order ()))
455     (labels ((rwalk (tail)
456     (when tail
457     (rwalk (cdr tail))
458     (dolist (ss (class-slots (car tail)))
459     (let ((n (slotd-name ss)))
460     (when (memq n names)
461     (setq order (cons n order)
462     names (remove n names))))))))
463     (rwalk cpl)
464     (reverse (append names order)))))
465    
466     (defun compute-class-slots (eslotds)
467     (gathering1 (collecting)
468     (dolist (eslotd eslotds)
469     (gather1
470     (assoc (slotd-name eslotd)
471     (class-slot-cells (slotd-allocation eslotd)))))))
472    
473     (defun update-inits (class inits)
474     (setf (plist-value class 'default-initargs) inits))
475    
476    
477     ;;;
478     ;;;
479     ;;;
480     (defmethod compute-default-initargs ((class std-class) cpl direct)
481     (labels ((walk (tail)
482     (if (null tail)
483     nil
484     (let ((c (pop tail)))
485     (append (if (eq c class)
486     direct
487     (class-direct-default-initargs c))
488     (walk tail))))))
489     (let ((initargs (walk cpl)))
490     (delete-duplicates initargs :test #'eq :key #'car :from-end t))))
491    
492    
493     ;;;
494     ;;; Protocols for constructing direct and effective slot definitions.
495     ;;;
496     ;;;
497     ;;;
498     ;;;
499     (defmethod direct-slot-definition-class ((class std-class) initargs)
500     (declare (ignore initargs))
501     (find-class 'standard-direct-slot-definition))
502    
503     (defun make-direct-slotd (class initargs)
504     (let ((initargs (list* :class class initargs)))
505     (apply #'make-instance (direct-slot-definition-class class initargs) initargs)))
506    
507     ;;;
508     ;;;
509     ;;;
510     (defmethod compute-slots ((class std-class) cpl class-direct-slots)
511     ;;
512     ;; As specified, we must call COMPUTE-EFFECTIVE-SLOT-DEFINITION once
513     ;; for each different slot name we find in our superclasses. Each
514     ;; call receives the class and a list of the dslotds with that name.
515     ;; The list is in most-specific-first order.
516     ;;
517     (let ((name-dslotds-alist ()))
518     (labels ((collect-one-class (dslotds)
519     (dolist (d dslotds)
520     (let* ((name (slotd-name d))
521     (entry (assq name name-dslotds-alist)))
522     (if entry
523     (push d (cdr entry))
524     (push (list name d) name-dslotds-alist))))))
525     (collect-one-class class-direct-slots)
526     (dolist (c (cdr cpl)) (collect-one-class (class-direct-slots c)))
527     (mapcar #'(lambda (direct)
528     (compute-effective-slot-definition class
529     (nreverse (cdr direct))))
530     name-dslotds-alist))))
531    
532     (defmethod compute-effective-slot-definition ((class std-class) dslotds)
533     (let* ((initargs (compute-effective-slot-definition-initargs class dslotds))
534     (class (effective-slot-definition-class class initargs)))
535     (apply #'make-instance class initargs)))
536    
537     (defmethod effective-slot-definition-class ((class std-class) initargs)
538     (declare (ignore initargs))
539     (find-class 'standard-effective-slot-definition))
540    
541     (defmethod compute-effective-slot-definition-initargs
542     ((class std-class) direct-slotds)
543     (let* ((name nil)
544     (initfunction nil)
545     (initform nil)
546     (initargs nil)
547     (allocation nil)
548     (type t)
549     (namep nil)
550     (initp nil)
551     (allocp nil))
552    
553     (dolist (slotd direct-slotds)
554     (when slotd
555     (unless namep
556     (setq name (slotd-name slotd)
557     namep t))
558     (unless initp
559     (when (slotd-initfunction slotd)
560     (setq initform (slotd-initform slotd)
561     initfunction (slotd-initfunction slotd)
562     initp t)))
563     (unless allocp
564     (setq allocation (slotd-allocation slotd)
565     allocp t))
566     (setq initargs (append (slotd-initargs slotd) initargs))
567     (let ((slotd-type (slotd-type slotd)))
568     (setq type (cond ((null type) slotd-type)
569     ((subtypep type slotd-type) type)
570     (t `(and ,type ,slotd-type)))))))
571     (list :name name
572     :initform initform
573     :initfunction initfunction
574     :initargs initargs
575     :allocation allocation
576     :type type)))
577    
578    
579     ;;;
580     ;;; NOTE: For bootstrapping considerations, these can't use make-instance
581     ;;; to make the method object. They have to use make-a-method which
582     ;;; is a specially bootstrapped mechanism for making standard methods.
583     ;;;
584     (defmethod add-reader-method ((class std-class) generic-function slot-name)
585     (let* ((name (class-name class))
586     (method (make-a-method 'standard-reader-method
587     ()
588     (list (or name 'standard-object))
589     (list class)
590     (make-reader-method-function class slot-name)
591     "automatically generated reader method"
592     slot-name)))
593     (add-method generic-function method)))
594    
595     (defmethod add-writer-method ((class std-class) generic-function slot-name)
596     (let* ((name (class-name class))
597     (method (make-a-method 'standard-writer-method
598     ()
599     (list 'new-value (or name 'standard-object))
600     (list *the-class-t* class)
601     (make-writer-method-function class slot-name)
602     "automatically generated writer method"
603     slot-name)))
604     (add-method generic-function method)))
605    
606    
607     (defmethod remove-reader-method ((class std-class) generic-function)
608     (let ((method (get-method generic-function () (list class) nil)))
609     (when method (remove-method generic-function method))))
610    
611     (defmethod remove-writer-method ((class std-class) generic-function)
612     (let ((method
613     (get-method generic-function () (list *the-class-t* class) nil)))
614     (when method (remove-method generic-function method))))
615    
616    
617     ;;;
618     ;;; make-reader-method-function and make-write-method function are NOT part of
619     ;;; the standard protocol. They are however useful, PCL makes uses makes use
620     ;;; of them internally and documents them for PCL users.
621     ;;;
622     ;;; *** This needs work to make type testing by the writer functions which
623     ;;; *** do type testing faster. The idea would be to have one constructor
624     ;;; *** for each possible type test. In order to do this it would be nice
625     ;;; *** to have help from inform-type-system-about-class and friends.
626     ;;;
627     ;;; *** There is a subtle bug here which is going to have to be fixed.
628     ;;; *** Namely, the simplistic use of the template has to be fixed. We
629     ;;; *** have to give the optimize-slot-value method the user might have
630     ;;; *** defined for this metclass a chance to run.
631     ;;;
632     (defmethod make-reader-method-function ((class standard-class) slot-name)
633     (make-std-reader-method-function slot-name))
634    
635     (defmethod make-writer-method-function ((class standard-class) slot-name)
636     (make-std-writer-method-function slot-name))
637    
638     (defun make-std-reader-method-function (slot-name)
639     #'(lambda (instance)
640 ram 1.2 (slot-value instance slot-name)))
641 wlott 1.1
642     (defun make-std-writer-method-function (slot-name)
643     #'(lambda (nv instance)
644 ram 1.2 (setf (slot-value instance slot-name) nv)))
645 wlott 1.1
646    
647    
648     ;;;; inform-type-system-about-class
649     ;;;; make-type-predicate
650     ;;;
651     ;;; These are NOT part of the standard protocol. They are internal mechanism
652     ;;; which PCL uses to *try* and tell the type system about class definitions.
653     ;;; In a more fully integrated implementation of CLOS, the type system would
654     ;;; know about class objects and class names in a more fundamental way and
655     ;;; the mechanism used to inform the type system about new classes would be
656     ;;; different.
657     ;;;
658     (defmethod inform-type-system-about-class ((class std-class) name)
659     (let ((predicate-name (make-type-predicate-name name)))
660     (setf (symbol-function predicate-name) (make-type-predicate name))
661     (do-satisfies-deftype name predicate-name)))
662    
663     (defun make-type-predicate (name)
664     #'(lambda (x)
665     (not
666     (null
667     (memq (find-class name)
668     (cond ((std-instance-p x)
669     (class-precedence-list (std-instance-class x)))
670     ((fsc-instance-p x)
671     (class-precedence-list (fsc-instance-class x)))))))))
672    
673    
674     ;;;
675     ;;; These 4 definitions appear here for bootstrapping reasons. Logically,
676     ;;; they should be in the construct file. For documentation purposes, a
677     ;;; copy of these definitions appears in the construct file. If you change
678     ;;; one of the definitions here, be sure to change the copy there.
679     ;;;
680     (defvar *initialization-generic-functions*
681     (list #'make-instance
682     #'default-initargs
683     #'allocate-instance
684     #'initialize-instance
685     #'shared-initialize))
686    
687     (defmethod maybe-update-constructors
688     ((generic-function generic-function)
689     (method method))
690     (when (memq generic-function *initialization-generic-functions*)
691     (labels ((recurse (class)
692     (update-constructors class)
693     (dolist (subclass (class-direct-subclasses class))
694     (recurse subclass))))
695     (when (classp (car (method-specializers method)))
696     (recurse (car (method-specializers method)))))))
697    
698     (defmethod update-constructors ((class std-class))
699     (dolist (cons (class-constructors class))
700     (install-lazy-constructor-installer cons)))
701    
702     (defmethod update-constructors ((class class))
703     ())
704    
705    
706    
707     (defmethod compatible-meta-class-change-p (class proto-new-class)
708     (eq (class-of class) (class-of proto-new-class)))
709    
710     (defmethod check-super-metaclass-compatibility ((class t) (new-super t))
711     (unless (eq (class-of class) (class-of new-super))
712     (error "The class ~S was specified as a~%super-class of the class ~S;~%~
713     but the meta-classes ~S and~%~S are incompatible."
714     new-super class (class-of new-super) (class-of class))))
715    
716    
717     ;;;
718     ;;;
719     ;;;
720     (defun force-cache-flushes (class)
721     (let* ((owrapper (class-wrapper class))
722     (state (wrapper-state owrapper)))
723     ;;
724     ;; We only need to do something if the state is still T. If the
725     ;; state isn't T, it will be FLUSH or OBSOLETE, and both of those
726     ;; will already be doing what we want. In particular, we must be
727     ;; sure we never change an OBSOLETE into a FLUSH since OBSOLETE
728     ;; means do what FLUSH does and then some.
729     ;;
730     (when (eq state 't)
731     (let ((nwrapper (make-wrapper class)))
732     (setf (wrapper-instance-slots-layout nwrapper)
733     (wrapper-instance-slots-layout owrapper))
734     (setf (wrapper-class-slots nwrapper)
735     (wrapper-class-slots owrapper))
736     (without-interrupts
737     (setf (slot-value class 'wrapper) nwrapper)
738     (invalidate-wrapper owrapper 'flush nwrapper))
739     (update-constructors class))))) ;??? ***
740    
741     (defun flush-cache-trap (owrapper nwrapper instance)
742     (declare (ignore owrapper))
743     (set-wrapper instance nwrapper))
744    
745    
746    
747     ;;;
748     ;;; make-instances-obsolete can be called by user code. It will cause the
749     ;;; next access to the instance (as defined in 88-002R) to trap through the
750     ;;; update-instance-for-redefined-class mechanism.
751     ;;;
752     (defmethod make-instances-obsolete ((class std-class))
753     (let ((owrapper (class-wrapper class))
754     (nwrapper (make-wrapper class)))
755     (setf (wrapper-instance-slots-layout nwrapper)
756     (wrapper-instance-slots-layout owrapper))
757     (setf (wrapper-class-slots nwrapper)
758     (wrapper-class-slots owrapper))
759     (without-interrupts
760     (setf (slot-value class 'wrapper) nwrapper)
761     (invalidate-wrapper owrapper 'obsolete nwrapper)
762     class)))
763    
764     (defmethod make-instances-obsolete ((class symbol))
765     (make-instances-obsolete (find-class class)))
766    
767    
768     ;;;
769     ;;; obsolete-instance-trap is the internal trap that is called when we see
770     ;;; an obsolete instance. The times when it is called are:
771     ;;; - when the instance is involved in method lookup
772     ;;; - when attempting to access a slot of an instance
773     ;;;
774     ;;; It is not called by class-of, wrapper-of, or any of the low-level instance
775     ;;; access macros.
776     ;;;
777     ;;; Of course these times when it is called are an internal implementation
778     ;;; detail of PCL and are not part of the documented description of when the
779     ;;; obsolete instance update happens. The documented description is as it
780     ;;; appears in 88-002R.
781     ;;;
782     ;;; This has to return the new wrapper, so it counts on all the methods on
783     ;;; obsolete-instance-trap-internal to return the new wrapper. It also does
784     ;;; a little internal error checking to make sure that the traps are only
785     ;;; happening when they should, and that the trap methods are computing
786     ;;; apropriate new wrappers.
787     ;;;
788     (defun obsolete-instance-trap (owrapper nwrapper instance)
789     ;;
790     ;; local --> local transfer
791     ;; local --> shared discard
792     ;; local --> -- discard
793     ;; shared --> local transfer
794     ;; shared --> shared discard
795     ;; shared --> -- discard
796     ;; -- --> local add
797     ;; -- --> shared --
798     ;;
799     (let* ((class (wrapper-class nwrapper))
800     (guts (allocate-instance class)) ;??? allocate-instance ???
801     (olayout (wrapper-instance-slots-layout owrapper))
802     (nlayout (wrapper-instance-slots-layout nwrapper))
803     (oslots (get-slots instance))
804     (nslots (get-slots guts))
805     (oclass-slots (wrapper-class-slots owrapper))
806     (added ())
807     (discarded ())
808     (plist ()))
809     ;;
810     ;; Go through all the old local slots.
811     ;;
812     (iterate ((name (list-elements olayout))
813     (opos (interval :from 0)))
814     (let ((npos (posq name nlayout)))
815     (if npos
816     (setf (svref nslots npos) (svref oslots opos))
817     (progn (push name discarded)
818     (unless (eq (svref oslots opos) *slot-unbound*)
819     (setf (getf plist name) (svref oslots opos)))))))
820     ;;
821     ;; Go through all the old shared slots.
822     ;;
823     (iterate ((oclass-slot-and-val (list-elements oclass-slots)))
824     (let ((name (car oclass-slot-and-val))
825     (val (cdr oclass-slot-and-val)))
826     (let ((npos (posq name nlayout)))
827     (if npos
828     (setf (svref nslots npos) (cdr oclass-slot-and-val))
829     (progn (push name discarded)
830     (unless (eq val *slot-unbound*)
831     (setf (getf plist name) val)))))))
832     ;;
833     ;; Go through all the new local slots to compute the added slots.
834     ;;
835     (dolist (nlocal nlayout)
836     (unless (or (memq nlocal olayout)
837     (assq nlocal oclass-slots))
838     (push nlocal added)))
839    
840     (without-interrupts
841     (set-wrapper instance nwrapper)
842     (set-slots instance nslots))
843    
844     (update-instance-for-redefined-class instance
845     added
846     discarded
847     plist)
848     nwrapper))
849    
850    
851    
852     ;;;
853     ;;;
854     ;;;
855     (defmacro change-class-internal (wrapper-fetcher slots-fetcher alloc)
856     `(let* ((old-class (class-of instance))
857     (copy (,alloc old-class))
858     (guts (,alloc new-class))
859     (new-wrapper (,wrapper-fetcher guts))
860     (old-wrapper (class-wrapper old-class))
861     (old-layout (wrapper-instance-slots-layout old-wrapper))
862     (new-layout (wrapper-instance-slots-layout new-wrapper))
863     (old-slots (,slots-fetcher instance))
864     (new-slots (,slots-fetcher guts))
865     (old-class-slots (wrapper-class-slots old-wrapper)))
866    
867     ;;
868     ;; "The values of local slots specified by both the class Cto and
869     ;; Cfrom are retained. If such a local slot was unbound, it remains
870     ;; unbound."
871     ;;
872     (iterate ((new-slot (list-elements new-layout))
873     (new-position (interval :from 0)))
874     (let ((old-position (position new-slot old-layout :test #'eq)))
875     (when old-position
876     (setf (svref new-slots new-position)
877     (svref old-slots old-position)))))
878    
879     ;;
880     ;; "The values of slots specified as shared in the class Cfrom and
881     ;; as local in the class Cto are retained."
882     ;;
883     (iterate ((slot-and-val (list-elements old-class-slots)))
884     (let ((position (position (car slot-and-val) new-layout :test #'eq)))
885     (when position
886     (setf (svref new-slots position) (cdr slot-and-val)))))
887    
888     ;; Make the copy point to the old instance's storage, and make the
889     ;; old instance point to the new storage.
890     (without-interrupts
891     (setf (,slots-fetcher copy) old-slots)
892    
893     (setf (,wrapper-fetcher instance) new-wrapper)
894     (setf (,slots-fetcher instance) new-slots))
895    
896     (update-instance-for-different-class copy instance)
897     instance))
898    
899     (defmethod change-class ((instance standard-object)
900     (new-class standard-class))
901     (unless (std-instance-p instance)
902     (error "Can't change the class of ~S to ~S~@
903     because it isn't already an instance with metaclass~%~S."
904     instance
905     new-class
906     'standard-class))
907     (change-class-internal std-instance-wrapper
908     std-instance-slots
909     allocate-instance))
910    
911     (defmethod change-class ((instance standard-object)
912     (new-class funcallable-standard-class))
913     (unless (fsc-instance-p instance)
914     (error "Can't change the class of ~S to ~S~@
915     because it isn't already an instance with metaclass~%~S."
916     instance
917     new-class
918     'funcallable-standard-class))
919     (change-class-internal fsc-instance-wrapper
920     fsc-instance-slots
921     allocate-instance))
922    
923     (defmethod change-class ((instance t) (new-class-name symbol))
924     (change-class instance (find-class new-class-name)))
925    
926    
927    
928     ;;;
929     ;;; The metaclass BUILT-IN-CLASS
930     ;;;
931     ;;; This metaclass is something of a weird creature. By this point, all
932     ;;; instances of it which will exist have been created, and no instance
933     ;;; is ever created by calling MAKE-INSTANCE.
934     ;;;
935     ;;; But, there are other parts of the protcol we must follow and those
936     ;;; definitions appear here.
937     ;;;
938     (defmethod shared-initialize :before
939     ((class built-in-class) slot-names &rest initargs)
940     (declare (ignore slot-names))
941     (error "Attempt to initialize or reinitialize a built in class."))
942    
943     (defmethod class-direct-slots ((class built-in-class)) ())
944     (defmethod class-slots ((class built-in-class)) ())
945     (defmethod class-direct-default-initargs ((class built-in-class)) ())
946     (defmethod class-default-initargs ((class built-in-class)) ())
947    
948     (defmethod check-super-metaclass-compatibility ((c class) (s built-in-class))
949     (or (eq s *the-class-t*)
950     (error "~S cannot have ~S as a super.~%~
951     The class ~S is the only built in class that can be a~%~
952     superclass of a standard class."
953     c s *the-class-t*)))
954    
955    
956     ;;;
957     ;;;
958     ;;;
959    
960     (defmethod check-super-metaclass-compatibility ((c std-class)
961     (f forward-referenced-class))
962     't)
963    
964    
965     ;;;
966     ;;;
967     ;;;
968    
969     (defmethod add-dependent ((metaobject dependent-update-mixin) dependent)
970     (pushnew dependent (plist-value metaobject 'dependents)))
971    
972     (defmethod remove-dependent ((metaobject dependent-update-mixin) dependent)
973     (setf (plist-value metaobject 'dependents)
974     (delete dependent (plist-value metaobject 'dependents))))
975    
976     (defmethod map-dependents ((metaobject dependent-update-mixin) function)
977     (dolist (dependent (plist-value metaobject 'dependents))
978 ram 1.2 (funcall function dependent)))
979    

  ViewVC Help
Powered by ViewVC 1.1.5