-
Notifications
You must be signed in to change notification settings - Fork 3
/
closette-final.lisp
233 lines (191 loc) · 8.56 KB
/
closette-final.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
(in-package #:closette)
(defgeneric print-object (instance stream))
(defmethod print-object ((instance standard-object) stream)
(print-unreadable-object (instance stream :identity t)
(format stream "~:(~S~)"
(class-name (class-of instance))))
instance)
;;; Slot access
(defgeneric slot-value-using-class (class instance slot-name))
(defmethod slot-value-using-class
((class standard-class) instance slot-name)
(std-slot-value instance slot-name))
(defgeneric (setf slot-value-using-class) (new-value class instance slot-name))
(defmethod (setf slot-value-using-class)
(new-value (class standard-class) instance slot-name)
(setf (std-slot-value instance slot-name) new-value))
;;; N.B. To avoid making a forward reference to a (setf xxx) generic function:
(defun setf-slot-value-using-class (new-value class object slot-name)
(setf (slot-value-using-class class object slot-name) new-value))
(defgeneric slot-exists-p-using-class (class instance slot-name))
(defmethod slot-exists-p-using-class
((class standard-class) instance slot-name)
(std-slot-exists-p instance slot-name))
(defgeneric slot-boundp-using-class (class instance slot-name))
(defmethod slot-boundp-using-class
((class standard-class) instance slot-name)
(std-slot-boundp instance slot-name))
(defgeneric slot-makunbound-using-class (class instance slot-name))
(defmethod slot-makunbound-using-class
((class standard-class) instance slot-name)
(std-slot-makunbound instance slot-name))
;;; Instance creation and initialization
(defgeneric allocate-instance (class))
(defmethod allocate-instance ((class standard-class))
(std-allocate-instance class))
(defgeneric make-instance (class &key))
(defmethod make-instance ((class standard-class) &rest initargs)
(let ((instance (allocate-instance class)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class symbol) &rest initargs)
(apply #'make-instance (find-class class) initargs))
(defgeneric initialize-instance (instance &key))
(defmethod initialize-instance ((instance standard-object) &rest initargs)
(apply #'shared-initialize instance t initargs))
(defgeneric reinitialize-instance (instance &key))
(defmethod reinitialize-instance
((instance standard-object) &rest initargs)
(apply #'shared-initialize instance () initargs))
(defgeneric shared-initialize (instance slot-names &key))
(defmethod shared-initialize ((instance standard-object)
slot-names &rest all-keys)
(dolist (slot (class-slots (class-of instance)))
(let ((slot-name (slot-definition-name slot)))
(multiple-value-bind (init-key init-value foundp)
(get-properties
all-keys (slot-definition-initargs slot))
(declare (ignore init-key))
(if foundp
(setf (slot-value instance slot-name) init-value)
(when (and (not (slot-boundp instance slot-name))
(not (null (slot-definition-initfunction slot)))
(or (eq slot-names t)
(member slot-name slot-names)))
(setf (slot-value instance slot-name)
(funcall (slot-definition-initfunction slot))))))))
instance)
;;; change-class
(defgeneric change-class (instance new-class &key))
(defmethod change-class
((old-instance standard-object)
(new-class standard-class)
&rest initargs)
(let ((new-instance (allocate-instance new-class)))
(dolist (slot-name (mapcar #'slot-definition-name
(class-slots new-class)))
(when (and (slot-exists-p old-instance slot-name)
(slot-boundp old-instance slot-name))
(setf (slot-value new-instance slot-name)
(slot-value old-instance slot-name))))
(rotatef (std-instance-slots new-instance)
(std-instance-slots old-instance))
(rotatef (std-instance-class new-instance)
(std-instance-class old-instance))
(apply #'update-instance-for-different-class
new-instance old-instance initargs)
old-instance))
(defmethod change-class
((instance standard-object) (new-class symbol) &rest initargs)
(apply #'change-class instance (find-class new-class) initargs))
(defgeneric update-instance-for-different-class (old new &key))
(defmethod update-instance-for-different-class
((old standard-object) (new standard-object) &rest initargs)
(let ((added-slots
(remove-if #'(lambda (slot-name)
(slot-exists-p old slot-name))
(mapcar #'slot-definition-name
(class-slots (class-of new))))))
(apply #'shared-initialize new added-slots initargs)))
;;;
;;; Methods having to do with class metaobjects.
;;;
(defmethod print-object ((class standard-class) stream)
(print-unreadable-object (class stream :identity t)
(format stream "~:(~S~) ~S"
(class-name (class-of class))
(class-name class)))
class)
(defmethod initialize-instance :after ((class standard-class) &rest args)
(apply #'std-after-initialization-for-classes class args))
;;; Finalize inheritance
(defgeneric finalize-inheritance (class))
(defmethod finalize-inheritance ((class standard-class))
(std-finalize-inheritance class)
(values))
;;; Class precedence lists
(defgeneric compute-class-precedence-list (class))
(defmethod compute-class-precedence-list ((class standard-class))
(std-compute-class-precedence-list class))
;;; Slot inheritance
(defgeneric compute-slots (class))
(defmethod compute-slots ((class standard-class))
(std-compute-slots class))
(defgeneric compute-effective-slot-definition (class direct-slots))
(defmethod compute-effective-slot-definition
((class standard-class) direct-slots)
(std-compute-effective-slot-definition class direct-slots))
;;;
;;; Methods having to do with generic function metaobjects.
;;;
(defmethod print-object ((gf standard-generic-function) stream)
(print-unreadable-object (gf stream :identity t)
(format stream "~:(~S~) ~S"
(class-name (class-of gf))
(generic-function-name gf)))
gf)
(defmethod initialize-instance :after ((gf standard-generic-function) &key)
(finalize-generic-function gf))
;;;
;;; Methods having to do with method metaobjects.
;;;
(defmethod print-object ((method standard-method) stream)
(print-unreadable-object (method stream :identity t)
(format stream "~:(~S~) ~S~{ ~S~} ~S"
(class-name (class-of method))
(generic-function-name
(method-generic-function method))
(method-qualifiers method)
(mapcar #'class-name
(method-specializers method))))
method)
(defmethod initialize-instance :after ((method standard-method) &key)
(setf (method-function method) (compute-method-function method)))
;;;
;;; Methods having to do with generic function invocation.
;;;
(defgeneric compute-discriminating-function (gf))
(defmethod compute-discriminating-function ((gf standard-generic-function))
(std-compute-discriminating-function gf))
(defgeneric method-more-specific-p (gf method1 method2 required-classes))
(defmethod method-more-specific-p
((gf standard-generic-function) method1 method2 required-classes)
(std-method-more-specific-p gf method1 method2 required-classes))
(defgeneric compute-effective-method-function (gf methods))
(defmethod compute-effective-method-function
((gf standard-generic-function) methods)
(std-compute-effective-method-function gf methods))
(defgeneric compute-method-function (method))
(defmethod compute-method-function ((method standard-method))
(std-compute-method-function method))
;;; describe-object is a handy tool for enquiring minds:
(defgeneric describe-object (object stream))
(defmethod describe-object ((object standard-object) stream)
(format t "A Closette object~
~%Printed representation: ~S~
~%Class: ~S~
~%Structure "
object
(class-of object))
(dolist (sn (mapcar #'slot-definition-name
(class-slots (class-of object))))
(format t "~% ~S <- ~:[not bound~;~S~]"
sn
(slot-boundp object sn)
(and (slot-boundp object sn)
(slot-value object sn))))
(values))
(defmethod describe-object ((object t) stream)
(common-lisp:describe object)
(values))
(format t "~%Closette is a Knights of the Lambda Calculus production.")