-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcomputed-metaclass.lisp
239 lines (197 loc) · 7.87 KB
/
computed-metaclass.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
233
234
235
236
237
238
;; computed-metaclass.lisp
;; --------------------------------------------------------------------------------------
;; Computed object metaclass. For Memory Mapped Computed Objects
;;
;; Not transactioned. Single user only.
;;
;; Copyright (C) 2008 by SpectroDynamics, LLC. All rights reserved.
;;
;; DM/SD 11/08
;; --------------------------------------------------------------------------------------
;; --------------------------------------------------
(in-package :useful-macros)
;; --------------------------------------------------
;; -----------------------------------------------------------
;; Computed-slot-definition
;; -----------------------------------------------------------
;; mixin metaclass for computed slots and methods to make them
;; appear normal
(defclass computed-slot-definition (clos:standard-slot-definition)
((function :initarg :function
:accessor computed-slot-definition-function)))
(defmethod slot-definition-allocation ((slotd computed-slot-definition))
:computed)
(defmethod (setf slot-definition-allocation) (allocation (slotd computed-slot-definition))
(unless (eq allocation :computed)
(error "Cannot change the allocation of a ~S"
'computed-direct-slot-definition))
allocation)
;; ---------------------------------------
;; class of direct computed slots and methods to construct them
;; when appropriate
(defclass computed-direct-slot-definition (clos:standard-direct-slot-definition
computed-slot-definition)
())
;; ---------------------------------------
;; Class of effective computed slots and methods to construct
;; them when appropriate
(defclass computed-effective-slot-definition
(clos:standard-effective-slot-definition
computed-slot-definition)
())
;; -----------------------------------------------------------
;; Computed-Metalevel-Class
;; --------------------------------------------------------------------------------------
;; metaclass of objects that might contain extended slots
(defclass computed-metalevel-class (#+:LISPWORKS clos:standard-class
#+:ALLEGRO clos::standard-class
#+:CLOZURE standard-class
#+:SBCL standard-class)
())
;; ---------------------------------------
;; Called when the class is being made, to choose the metaclass of
;; a given direct slot. It should return the class of slot definition required.
(defmethod clos:direct-slot-definition-class
((class computed-metalevel-class) &rest initargs)
(case (getf initargs :allocation)
(:computed
(find-class 'computed-direct-slot-definition))
(t
(call-next-method))))
;; ---------------------------------------
;; Called when the defclass is expanded, to process a slot option.
;; It should return the new list of slot options, based on
;; already-processed-options.
#+:LISPWORKS
(defmethod clos:process-a-slot-option ((class computed-metalevel-class) option value
already-processed-options slot)
;; Hande the :function option by adding it to the list of
;; processed options.
(case option
(:function (list* :function value already-processed-options))
(t (call-next-method))
))
;; --------------------------------------------------------------
;; Called when the class is being finalized, to choose the
;; metaclass of a given effective slot. It should return the
;; class of slot definition required.
(defmethod clos:effective-slot-definition-class
((class computed-metalevel-class) &rest initargs)
;; Use computed-effective-slot-definition if appropriate
(let ((slot-allocation (getf initargs :allocation)))
(case slot-allocation
(:computed
(find-class 'computed-effective-slot-definition))
(t (call-next-method))
)))
;; ------------------------------------------------------------
(defmethod clos:compute-effective-slot-definition
((class computed-metalevel-class)
slot-name
direct-slot-definitions)
(declare (ignore slot-name))
(let ((effective-slotdef (call-next-method)))
(dolist (slotd direct-slot-definitions)
(typecase slotd
(computed-slot-definition
(setf (computed-slot-definition-function effective-slotdef)
(computed-slot-definition-function slotd))
(return))
))
effective-slotdef))
;; -------------------------------------------------------------------
;; underlying access methods for invoking
;; computed-slot-definition-function.
#+(OR :LISPWORKS :ALLEGRO)
(defmethod clos:slot-value-using-class
((class computed-metalevel-class) object slot-name)
(let ((slotd (find slot-name (clos:class-slots class)
:key 'clos:slot-definition-name)))
(typecase slotd
(computed-slot-definition
(funcall (computed-slot-definition-function slotd)
:get object))
(t (call-next-method))
)))
#+(OR :CLOZURE :SBCL)
(defmethod clos:slot-value-using-class
((class computed-metalevel-class) object slot-def)
(typecase slot-def
(computed-slot-definition
(funcall (computed-slot-definition-function slot-def)
:get object))
(t (call-next-method))
))
;; ---------------------------------------
#+(OR :LISPWORKS :ALLEGRO)
(defmethod (setf clos:slot-value-using-class)
(value (class computed-metalevel-class) object slot-name)
(let ((slotd (find slot-name (clos:class-slots class)
:key 'clos:slot-definition-name)))
(typecase slotd
(computed-slot-definition
(funcall (computed-slot-definition-function slotd)
:set object value))
(t (call-next-method))
)))
#+(OR :CLOZURE :SBCL)
(defmethod (setf clos:slot-value-using-class)
(value (class computed-metalevel-class) object slot-def)
(typecase slot-def
(computed-slot-definition
(funcall (computed-slot-definition-function slot-def)
:set object value))
(t (call-next-method))
))
;; ---------------------------------------
;; not needed since we appear to be a normal instance slot
#+(OR :LISPWORKS :ALLEGRO)
(defmethod clos:slot-boundp-using-class
((class computed-metalevel-class) object slot-name)
(let ((slotd (find slot-name (clos:class-slots class)
:key 'clos:slot-definition-name)))
(typecase slotd
(computed-slot-definition
(funcall (computed-slot-definition-function slotd)
:is-set object))
(t (call-next-method))
)))
#+(OR :CLOZURE :SBCL)
(defmethod clos:slot-boundp-using-class
((class computed-metalevel-class) object slot-def)
(typecase slot-def
(computed-slot-definition
(funcall (computed-slot-definition-function slot-def)
:is-set object))
(t (call-next-method))
))
;; ---------------------------------------
#+(OR :LISPWORKS :ALLEGRO)
(defmethod clos:slot-makunbound-using-class
((class computed-metalevel-class) object slot-name)
(let ((slotd (find slot-name (clos:class-slots class)
:key 'clos:slot-definition-name)))
(typecase slotd
(computed-slot-definition
(funcall (computed-slot-definition-function slotd)
:unset object))
(t (call-next-method))
)))
#+(OR :CLOZURE :SBCL)
(defmethod clos:slot-makunbound-using-class
((class computed-metalevel-class) object slot-def)
(typecase slot-def
(computed-slot-definition
(funcall (computed-slot-definition-function slot-def)
:unset object))
(t (call-next-method))
))
;; ---------------------------------------
;; is this method really necessary?
#+:LISPWORKS
(defmethod clos:slot-exists-p-using-class
((class computed-metalevel-class) object slot-name)
(or (call-next-method)
(and (find slot-name (clos:class-slots class)
:key 'clos:slot-definition-name)
t)))