chiark / gitweb /
src/: Yet more naming and export twiddles.
[sod] / src / class-layout-proto.lisp
CommitLineData
dea4d055
MW
1;;; -*-lisp-*-
2;;;
3;;; Class layout protocol
4;;;
5;;; (c) 2009 Straylight/Edgeware
6;;;
7
8;;;----- Licensing notice ---------------------------------------------------
9;;;
10;;; This file is part of the Sensble Object Design, an object system for C.
11;;;
12;;; SOD is free software; you can redistribute it and/or modify
13;;; it under the terms of the GNU General Public License as published by
14;;; the Free Software Foundation; either version 2 of the License, or
15;;; (at your option) any later version.
16;;;
17;;; SOD is distributed in the hope that it will be useful,
18;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;;; GNU General Public License for more details.
21;;;
22;;; You should have received a copy of the GNU General Public License
23;;; along with SOD; if not, write to the Free Software Foundation,
24;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26(cl:in-package #:sod)
27
28;;;--------------------------------------------------------------------------
29;;; Effective slot objects.
30
31(export '(effective-slot effective-slot-class
32 effective-slot-direct-slot effective-slot-initializer))
33(defclass effective-slot ()
4b8e5c03 34 ((%class :initarg :class :type sod-slot :reader effective-slot-class)
dea4d055
MW
35 (slot :initarg :slot :type sod-slot :reader effective-slot-direct-slot)
36 (initializer :initarg :initializer :type (or sod-initializer null)
37 :reader effective-slot-initializer))
38 (:documentation
39 "Describes a slot and how it's meant to be initialized.
40
41 Specifically, an effective slot object states that in an instance of
42 CLASS, a particular SLOT is initializd by a particular INITIALIZER. Note
43 that the CLASS is a subclass of the SLOT's defining class, and not
44 necessarily the same.
45
46 Effective slot objects are usually found in `islots' objects."))
47
48(export 'find-slot-initializer)
49(defgeneric find-slot-initializer (class slot)
50 (:documentation
51 "Return the most specific initializer for SLOT, starting from CLASS."))
52
53(export 'compute-effective-slot)
54(defgeneric compute-effective-slot (class slot)
55 (:documentation
56 "Construct an effective slot from the supplied direct slot.
57
58 SLOT is a direct slot defined on CLASS or one of its superclasses.
59 (Metaclass initializers are handled using a different mechanism.)"))
60
61;;;--------------------------------------------------------------------------
62;;; Instance layout.
63
64;;; islots
65
66(export '(islots islots-class islots-subclass islots-slots))
67(defclass islots ()
4b8e5c03 68 ((%class :initarg :class :type sod-class :reader islots-class)
dea4d055
MW
69 (subclass :initarg :subclass :type sod-class :reader islots-subclass)
70 (slots :initarg :slots :type list :reader islots-slots))
71 (:documentation
72 "Contains effective slot definitions for a class's direct slots.
73
74 In detail: SLOTS is a list of effective slot objects corresponding to
75 CLASS's direct slots, and containing initializers computed relative to
76 SUBCLASS."))
77
78(export 'compute-islots)
79(defgeneric compute-islots (class subclass)
80 (:documentation
81 "Return `islots' for a particular CLASS and SUBCLASS.
82
83 Initializers for the slots should be taken from the most specific
84 superclass of SUBCLASS."))
85
86;;; vtable-pointer
87
88(export '(vtable-pointer vtable-pointer-class
89 vtable-pointer-chain-head vtable-pointer-chain-tail))
90(defclass vtable-pointer ()
4b8e5c03 91 ((%class :initarg :class :type sod-class :reader vtable-pointer-class)
dea4d055
MW
92 (chain-head :initarg :chain-head :type sod-class
93 :reader vtable-pointer-chain-head)
94 (chain-tail :initarg :chain-tail :type sod-class
95 :reader vtable-pointer-chain-tail))
96 (:documentation
97 "Represents a pointer to a class's vtable.
98
99 There's one of these for each of CLASS's chains. This particular one
100 belongs to the chain headed by CHAIN-HEAD; the most specific superclass of
101 CLASS on that chain is CHAIN-TAIL. (The tail is useful because we can --
102 and do -- use structure types defined by the tail class for non-primary
103 chains.)"))
104
105;;; ichain
106
107(export '(ichain ichain-class ichain-head ichain-tail ichain-body))
108(defclass ichain ()
4b8e5c03 109 ((%class :initarg :class :type sod-class :reader ichain-class)
dea4d055
MW
110 (chain-head :initarg :chain-head :type sod-class :reader ichain-head)
111 (chain-tail :initarg :chain-tail :type sod-class :reader ichain-tail)
112 (body :initarg :body :type list :reader ichain-body))
113 (:documentation
114 "Contains instance data for a particular chain of superclasses.
115
116 In detail: describes instance data for one of CLASS's chains, specifically
117 the chain headed by CHAIN-HEAD. The CHAIN-TAIL is the most specific
118 superclass of CLASS on the chain in question. The BODY is a list of
119 layout objects to be included.
120
121 An `ilayout' object maintains a list of `ichain' objects, one for each of
122 a class's chains."))
123
124(export 'compute-ichain)
125(defgeneric compute-ichain (class chain)
126 (:documentation
127 "Return an ICHAIN for a particular CHAIN of CLASS's superclasses.
128
129 The CHAIN is a list of classes, with the least specific first -- so the
130 chain head is the first element."))
131
132;;; ilayout
133
134(export '(ilayout ilayout-class ilayout-ichains))
135(defclass ilayout ()
4b8e5c03 136 ((%class :initarg :class :type sod-class :reader ilayout-class)
dea4d055
MW
137 (ichains :initarg :ichains :type list :reader ilayout-ichains))
138 (:documentation
139 "All of the instance layout for a class.
140
141 Describes the layout of an instance of CLASS. The list ICHAINS contains
142 an `ichain' object for each chain of CLASS."))
143
144(export 'compute-ilayout)
145(defgeneric compute-ilayout (class)
146 (:documentation
147 "Compute and return an instance layout for CLASS."))
148
149;;;--------------------------------------------------------------------------
150;;; Vtable layout.
151
152;;; vtmsgs
153
7f2917d2
MW
154(export '(vtmsgs vtmsgs-class vtmsgs-subclass
155 vtmsgs-chain-head vtmsgs-chain-tail vtmsgs-entries))
dea4d055 156(defclass vtmsgs ()
4b8e5c03 157 ((%class :initarg :class :type sod-class :reader vtmsgs-class)
dea4d055
MW
158 (subclass :initarg :subclass :type sod-class :reader vtmsgs-subclass)
159 (chain-head :initarg :chain-head :type sod-class
160 :reader vtmsgs-chain-head)
161 (chain-tail :initarg :chain-tail :type sod-class
162 :reader vtmsgs-chain-tail)
163 (entries :initarg :entries :type list :reader vtmsgs-entries))
164 (:documentation
165 "The message dispatch table for a particular class.
166
167 In detail, this lists the `method-entry' objects for the messages defined
168 by a particular CLASS, where the effective methods are specialized for the
169 SUBCLASS; the method entries adjust the instance pointer argument
170 appropriately for a call via the vtable for the chain headed by
171 CHAIN-HEAD. The CHAIN-TAIL is the most specific superclass of SUBCLASS on
172 this chain. The ENTRIES are a list of `method-entry' objects."))
173
93348ae9 174(export 'compute-vtmsgs)
dea4d055
MW
175(defgeneric compute-vtmsgs (class subclass chain-head chain-tail)
176 (:documentation
2aa51854 177 "Return a `vtmsgs' object containing method entries for CLASS.
dea4d055
MW
178
179 The CHAIN-HEAD describes which chain the method entries should be
180 constructed for.
181
2aa51854
MW
182 The default method simply calls `make-method-entry' for each of the
183 methods and wraps a `vtmsgs' object around them. This ought to be enough
184 for almost all purposes."))
dea4d055
MW
185
186;;; class-pointer
187
188(export '(class-pointer class-pointer-class class-pointer-chain-head
189 class-pointer-metaclass class-pointer-meta-chain-head))
190(defclass class-pointer ()
4b8e5c03 191 ((%class :initarg :class :type sod-class :reader class-pointer-class)
dea4d055
MW
192 (chain-head :initarg :chain-head :type sod-class
193 :reader class-pointer-chain-head)
194 (metaclass :initarg :metaclass :type sod-class
195 :reader class-pointer-metaclass)
196 (meta-chain-head :initarg :meta-chain-head :type sod-class
197 :reader class-pointer-meta-chain-head))
198 (:documentation
199 "Represents a pointer to a class object for the instance's class.
200
201 This is somewhat complicated because there are two degrees of freedom. An
202 instance of `class-pointer' is a pointer from a vtable to an `ichain' of
5608b1af 203 the the class's metaclass instance. In particular, a `class-pointer'
dea4d055
MW
204 instance represents a pointer in a vtable constructed for CLASS and
205 attached to the chain headed by CHAIN-HEAD; it points to an instance of
206 METACLASS, and specifically to the `ichain' substructure corresponding to
207 the chain headed by META-CHAIN-HEAD, which will be a superclass of
208 METACLASS.
209
210 I'm sorry if this is confusing."))
211
212(export 'make-class-pointer)
213(defgeneric make-class-pointer (class chain-head metaclass meta-chain-head)
214 (:documentation
215 "Return a class pointer to a metaclass chain."))
216
217;;; base-offset
218
219(export '(base-offset base-offset-class base-offset-chain-head))
220(defclass base-offset ()
4b8e5c03 221 ((%class :initarg :class :type sod-class :reader base-offset-class)
dea4d055
MW
222 (chain-head :initarg :chain-head :type sod-class
223 :reader base-offset-chain-head))
224 (:documentation
225 "The offset of this chain to the `ilayout' base.
226
227 We're generating a vtable for CLASS, attached to the chain headed by
228 CHAIN-HEAD. Fortunately (and unlike `class-pointer'), the chain head can
229 do double duty, since it also identifies the `ichain' substructure of the
230 class's `ilayout' whose offset we're interested in."))
231
232(export 'make-base-offset)
233(defgeneric make-base-offset (class chain-head)
234 (:documentation
235 "Return the base offset object for CHAIN-HEAD ichain."))
236
237;;; chain-offset
238
239(export '(chain-offset chain-offset-class
240 chain-offset-chain-head chain-offset-target-head))
241(defclass chain-offset ()
4b8e5c03 242 ((%class :initarg :class :type sod-class :reader chain-offset-class)
dea4d055
MW
243 (chain-head :initarg :chain-head :type sod-class
244 :reader chain-offset-chain-head)
245 (target-head :initarg :target-head :type sod-class
246 :reader chain-offset-target-head))
247 (:documentation
248 "The offset to a different `ichain'.
249
250 We're generating a vtable for CLASS, attached to the chain headed by
251 CHAIN-HEAD. This instance represents an offset to the (different) chain
252 headed by TARGET-HEAD.
253
254 This is, strictly speaking, redundant. We could do as well by using the
255 base offset and finding the offset to the target class in the class
256 object's metadata; but that would either require a search or we'd have to
257 be able work out the target chain's index in the table."))
258
259(defgeneric make-chain-offset (class chain-head target-head)
260 (:documentation
261 "Return the offset from CHAIN-HEAD to TARGET-HEAD."))
262
263;;; vtable
264
265(export '(vtable vtable-class vtable-body
266 vtable-chain-head vtable-chain-tail))
267(defclass vtable ()
4b8e5c03 268 ((%class :initarg :class :type sod-class :reader vtable-class)
dea4d055
MW
269 (chain-head :initarg :chain-head :type sod-class
270 :reader vtable-chain-head)
271 (chain-tail :initarg :chain-tail :type sod-class
272 :reader vtable-chain-tail)
273 (body :initarg :body :type list :reader vtable-body))
274 (:documentation
275 "A vtable holds all of the per-chain static information for a class.
276
277 Each chain of CLASS has its own vtable; the `vtable' object remembers the
278 least specific (CHAIN-HEAD) and most specific (CHAIN-TAIL) superclasses of
279 CLASS on that chain. (This is useful because we can reuse vtable
280 structure types from superclasses for chains other than the primary chain
281 -- i.e., the one in which CLASS itself appears.)
282
283 The BODY is a list of vtable items, including `vtmsgs' structures,
284 `chain-offset's, `class-pointers', and a `base-offset'."))
285
286(export 'compute-vtable-items)
287(defgeneric compute-vtable-items (class super chain-head chain-tail emit)
288 (:documentation
289 "Emit vtable items for a superclass of CLASS.
290
291 This function is called for each superclass SUPER of CLASS reached on the
292 chain headed by CHAIN-HEAD. The function should call EMIT for each
293 vtable item it wants to write.
294
295 The right way to check to see whether items have already been emitted
296 (e.g., has an offset to some other chain been emitted?) is as follows:
297
298 * In a method (ideally an `:around'-method) on `compute-vtable', bind a
299 special variable to an empty list or hash table.
300
301 * In a method on this function, check the variable or hash table.
302
303 This function is the real business end of `compute-vtable'."))
304
305(export 'compute-vtable)
306(defgeneric compute-vtable (class chain)
307 (:documentation
308 "Compute the vtable layout for a chain of CLASS.
309
310 The CHAIN is a list of classes, with the least specific first.
311
312 There is a default method which invokes `compute-vtable-items' to do the
313 difficult work."))
314
315(export 'compute-vtables)
316(defgeneric compute-vtables (class)
317 (:documentation
318 "Compute the vtable layouts for CLASS.
319
320 Returns a list of VTABLE objects in the order of CLASS's chains."))
321
322;;;----- That's all, folks --------------------------------------------------