New feature: proper object lifecycle protocol; init and teardown fragments.
[sod] / src / classes.lisp
CommitLineData
abdf50aa
MW
1;;; -*-lisp-*-
2;;;
dea4d055 3;;; Class definitions for main classes
abdf50aa
MW
4;;;
5;;; (c) 2009 Straylight/Edgeware
6;;;
7
8;;;----- Licensing notice ---------------------------------------------------
9;;;
e0808c47 10;;; This file is part of the Sensible Object Design, an object system for C.
abdf50aa
MW
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
59146e6e
MW
28;;; Note! You'll notice that none of the classes defined here store property
29;;; sets persistently, even though there's a `:pset' keyword argument
30;;; accepted by many of the classes' initialization methods. That's because
31;;; part of the pset protocol involves checking that there are no unused
32;;; properties, and this typically happens shortly after the appropriate
33;;; objects are constructed. It would be tempting to stash the pset at
34;;; initialization time, and then pick some property from it out later -- but
35;;; that won't work in general because an error might have been signalled
36;;; about that property. It wouldn't surprise me greatly to discover that
37;;; `most' code paths resulted in the property being looked up in time to
38;;; avoid the unused-property error, but a subtle change in circumstances
39;;; then causes a thing done on demand to be done later, leading to
40;;; irritating and misleading errors being reported to the user. So please
41;;; don't do that.
42
abdf50aa 43;;;--------------------------------------------------------------------------
1f1d88f5 44;;; Classes.
abdf50aa 45
dea4d055
MW
46(export '(sod-class sod-class-name sod-class-nickname
47 sod-class-type sod-class-metaclass
48 sod-class-direct-superclasses sod-class-precedence-list
49 sod-class-chain-link sod-class-chain-head
50 sod-class-chain sod-class-chains
a42893dd 51 sod-class-slots sod-class-initfrags sod-class-tearfrags
dea4d055
MW
52 sod-class-instance-initializers sod-class-class-initializers
53 sod-class-messages sod-class-methods
54 sod-class-state
55 sod-class-ilayout sod-class-vtables))
abdf50aa 56(defclass sod-class ()
77027cca
MW
57 ((name :initarg :name :type string :reader sod-class-name)
58 (location :initarg :location :initform (file-location nil)
59 :type file-location :reader file-location)
60 (nickname :initarg :nick :type string :reader sod-class-nickname)
61 (direct-superclasses :initarg :superclasses :type list
abdf50aa 62 :reader sod-class-direct-superclasses)
77027cca 63 (chain-link :initarg :link :type (or sod-class null)
1f1d88f5 64 :reader sod-class-chain-link)
77027cca 65 (metaclass :initarg :metaclass :type sod-class
abdf50aa 66 :reader sod-class-metaclass)
77027cca
MW
67 (slots :initarg :slots :initform nil
68 :type list :accessor sod-class-slots)
69 (instance-initializers :initarg :instance-initializers :initform nil
abdf50aa 70 :type list
abdf50aa 71 :accessor sod-class-instance-initializers)
77027cca
MW
72 (class-initializers :initarg :class-initializers :initform nil
73 :type list :accessor sod-class-class-initializers)
a42893dd
MW
74 (initfrags :initarg :initfrags :initform nil
75 :type list :accessor sod-class-initfrags)
76 (tearfrags :initarg :tearfrags :initform nil
77 :type list :accessor sod-class-tearfrags)
77027cca
MW
78 (messages :initarg :messages :initform nil
79 :type list :accessor sod-class-messages)
80 (methods :initarg :methods :initform nil
81 :type list :accessor sod-class-methods)
abdf50aa 82
16f9fb72 83 (class-precedence-list :type list :reader sod-class-precedence-list)
abdf50aa 84
16f9fb72 85 (%type :type c-class-type :reader sod-class-type)
ddee4bb1 86
16f9fb72
MW
87 (chain-head :type sod-class :reader sod-class-chain-head)
88 (chain :type list :reader sod-class-chain)
89 (chains :type list :reader sod-class-chains)
abdf50aa 90
16f9fb72
MW
91 (%ilayout :type ilayout :reader sod-class-ilayout)
92 (effective-methods :type list :reader sod-class-effective-methods)
93 (vtables :type list :reader sod-class-vtables)
1f1d88f5 94
1645e433 95 (state :initform nil :type (member nil :finalized :broken)
16f9fb72 96 :reader sod-class-state))
abdf50aa
MW
97 (:documentation
98 "Classes describe the layout and behaviour of objects.
99
1f1d88f5 100 The NAME, LOCATION, NICKNAME, DIRECT-SUPERCLASSES, CHAIN-LINK and
abdf50aa
MW
101 METACLASS slots are intended to be initialized when the class object is
102 constructed:
103
104 * The NAME is the identifier associated with the class in the user's
105 source file. It is used verbatim in the generated C code as a type
106 name, and must be distinct from other file-scope names in any source
107 file which includes the class definition. Furthermore, other names
108 are derived from the class name (most notably the class object
109 NAME__class), which have external linkage and must therefore be
110 distinct from all other identifiers in the program. It is forbidden
111 for a class NAME to begin with an underscore or to contain two
112 consecutive underscores.
113
114 * The LOCATION identifies where in the source the class was defined. It
115 gets used in error messages.
116
117 * The NICKNAME is a shorter identifier used to name the class in some
118 circumstances. The uniqueness requirements on NICKNAME are less
119 strict, which allows them to be shorter: no class may have two classes
120 with the same nickname on its class precedence list. Nicknames are
121 used (user-visibly) to distinguish slots and messages defined by
122 different classes, and (invisibly) in the derived names of direct
123 methods. It is forbidden for a nickname to begin with an underscore,
124 or to contain two consecutive underscores.
125
126 * The DIRECT-SUPERCLASSES are a list of the class's direct superclasses,
127 in the order that they were declared in the source. The class
128 precedence list is computed from the DIRECT-SUPERCLASSES lists of all
129 of the superclasses involved.
130
1f1d88f5
MW
131 * The CHAIN-LINK is either NIL or one of the DIRECT-SUPERCLASSES. Class
132 chains are a means for recovering most of the benefits of simple
133 hierarchy lost by the introduction of multiple inheritance. A class's
134 superclasses (including itself) are partitioned into chains,
135 consisting of a class, its CHAIN-LINK superclass, that class's
136 CHAIN-LINK, and so on. It is an error if two direct subclasses of any
137 class appear in the same chain (a global property which requires
138 global knowledge of an entire program's class hierarchy in order to
139 determine sensibly). Slots of superclasses in the same chain can be
140 accessed efficiently; there is an indirection needed to access slots
141 of superclasses in other chains. Furthermore, an indirection is
142 required to perform a cross-chain conversion (i.e., converting a
143 pointer to an instance of some class into a pointer to an instance of
144 one of its superclasses in a different chain), an operation which
145 occurs implicitly in effective methods in order to call direct methods
146 defined on cross-chain superclasses.
abdf50aa
MW
147
148 * The METACLASS is the class of the class object. Classes are objects
149 in their own right, and therefore must be instances of some class;
150 this class is the metaclass. Metaclasses can define additional slots
151 and methods to be provided by their instances; a class definition can
152 provide (C constant expression) initial values for the metaclass
153 instance.
154
155 The next few slots can't usually be set at object-construction time, since
156 the objects need to contain references to the class object itself.
157
158 * The SLOTS are a list of the slots defined by the class (instances of
dea4d055 159 `sod-slot'). (The class will also define all of the slots defined by
abdf50aa
MW
160 its superclasses.)
161
162 * The INSTANCE-INITIALIZERS and CLASS-INITIALIZERS are lists of
dea4d055
MW
163 initializers for slots (see `sod-initializer' and subclasses),
164 providing initial values for instances of the class, and for the
165 class's class object itself, respectively.
abdf50aa
MW
166
167 * The MESSAGES are a list of the messages recognized by the class
dea4d055 168 (instances of `sod-message' and subclasses). (Note that the message
abdf50aa
MW
169 need not have any methods defined on it. The class will also
170 recognize all of the messages defined by its superclasses.)
171
172 * The METHODS are a list of (direct) methods defined on the class
dea4d055 173 (instances of `sod-method' and subclasses). Each method provides
abdf50aa
MW
174 behaviour to be invoked by a particular message recognized by the
175 class.
176
177 Other slots are computed from these in order to describe the class's
dea4d055 178 layout and effective methods; this is done by `finalize-sod-class'.
abdf50aa 179
1f1d88f5 180 * The CLASS-PRECEDENCE-LIST is a list of superclasses in a linear order.
dea4d055
MW
181 It is computed by `compute-class-precedence-list', whose default
182 implementation ensures that the order of superclasses is such that (a)
183 subclasses appear before their superclasses; (b) the direct
184 superclasses of a given class appear in the order in which they were
185 declared by the programmer; and (c) classes always appear in the same
186 relative order in all class precedence lists in the same superclass
187 graph.
1f1d88f5
MW
188
189 * The CHAIN-HEAD is the least-specific class in the class's chain. If
190 there is no link class then the CHAIN-HEAD is the class itself. This
191 slot, like the next two, is computed by the generic function
dea4d055 192 `compute-chains'.
1f1d88f5
MW
193
194 * The CHAIN is the list of classes on the complete primary chain,
195 starting from this class and ending with the CHAIN-HEAD.
196
197 * The CHAINS are the complete collection of chains (most-to-least
198 specific) for the class and all of its superclasses.
199
dea4d055 200 Finally, slots concerning the instance and vtable layout of the class are
6e6b0958 201 computed on demand (see `define-on-demand-slot').
dea4d055 202
1f1d88f5 203 * The ILAYOUT describes the layout for an instance of the class. It's
2aa51854 204 quite complicated; see the documentation of the `ilayout' class for
1f1d88f5
MW
205 detais.
206
207 * The EFFECTIVE-METHODS are a list of effective methods, specialized for
208 the class.
209
210 * The VTABLES are a list of descriptions of vtables for the class. The
2aa51854
MW
211 individual elements are `vtable' objects, which are even more
212 complicated than `ilayout' structures. See the class documentation
213 for details."))
abdf50aa
MW
214
215(defmethod print-object ((class sod-class) stream)
1f1d88f5
MW
216 (maybe-print-unreadable-object (class stream :type t)
217 (princ (sod-class-name class) stream)))
218
219;;;--------------------------------------------------------------------------
220;;; Slots and initializers.
221
dea4d055 222(export '(sod-slot sod-slot-name sod-slot-class sod-slot-type))
1f1d88f5 223(defclass sod-slot ()
77027cca
MW
224 ((name :initarg :name :type string :reader sod-slot-name)
225 (location :initarg :location :initform (file-location nil)
226 :type file-location :reader file-location)
4b8e5c03
MW
227 (%class :initarg :class :type sod-class :reader sod-slot-class)
228 (%type :initarg :type :type c-type :reader sod-slot-type))
1f1d88f5
MW
229 (:documentation
230 "Slots are units of information storage in instances.
231
232 Each class defines a number of slots, which function similarly to (data)
233 members in structures. An instance contains all of the slots defined in
234 its class and all of its superclasses.
235
236 A slot carries the following information.
237
238 * A NAME, which distinguishes it from other slots defined by the same
239 class. Unlike most (all?) other object systems, slots defined in
240 different classes are in distinct namespaces. There are no special
241 restrictions on slot names.
242
243 * A LOCATION, which states where in the user's source the slot was
244 defined. This gets used in error messages.
245
246 * A CLASS, which states which class defined the slot. The slot is
247 available in instances of this class and all of its descendents.
248
249 * A TYPE, which is the C type of the slot. This must be an object type
250 (certainly not a function type, and it must be a complete type by the
251 time that the user header code has been scanned)."))
252
253(defmethod print-object ((slot sod-slot) stream)
254 (maybe-print-unreadable-object (slot stream :type t)
255 (pprint-c-type (sod-slot-type slot) stream
256 (format nil "~A.~A"
257 (sod-class-nickname (sod-slot-class slot))
258 (sod-slot-name slot)))))
259
dea4d055 260(export '(sod-initializer sod-initializer-slot sod-initializer-class
a888e3ac 261 sod-initializer-value))
1f1d88f5 262(defclass sod-initializer ()
77027cca
MW
263 ((slot :initarg :slot :type sod-slot :reader sod-initializer-slot)
264 (location :initarg :location :initform (file-location nil)
265 :type file-location :reader file-location)
4b8e5c03 266 (%class :initarg :class :type sod-class :reader sod-initializer-class)
a888e3ac 267 (value :initarg :value :type c-fragment :reader sod-initializer-value))
1f1d88f5
MW
268 (:documentation
269 "Provides an initial value for a slot.
270
271 The slots of an initializer are as follows.
272
273 * The SLOT specifies which slot this initializer is meant to initialize.
274
275 * The LOCATION states the position in the user's source file where the
276 initializer was found. This gets used in error messages. (Depending
277 on the source layout style, this might differ from the location in the
a888e3ac 278 VALUE C fragment.)
1f1d88f5
MW
279
280 * The CLASS states which class defined this initializer. For instance
dea4d055
MW
281 slot initializers (`sod-instance-initializer'), this will be the same
282 as the SLOT's class, or be one of its descendants. For class slot
283 initializers (`sod-class-initializer'), this will be an instance of
284 the SLOT's class, or an instance of one of its descendants.
1f1d88f5 285
a888e3ac 286 * The VALUE gives the text of the initializer, as a C fragment.
1f1d88f5
MW
287
288 Typically you'll see instances of subclasses of this class in the wild
dea4d055
MW
289 rather than instances of this class directly. See `sod-class-initializer'
290 and `sod-instance-initializer'."))
1f1d88f5
MW
291
292(defmethod print-object ((initializer sod-initializer) stream)
a888e3ac 293 (with-slots (slot value) initializer
882412cf
MW
294 (if *print-escape*
295 (print-unreadable-object (initializer stream :type t)
a888e3ac
MW
296 (format stream "~A = ~A" slot value))
297 (format stream "~A" value))))
1f1d88f5 298
dea4d055 299(export 'sod-class-initializer)
1f1d88f5
MW
300(defclass sod-class-initializer (sod-initializer)
301 ()
302 (:documentation
303 "Provides an initial value for a class slot.
304
305 A class slot initializer provides an initial value for a slot in the class
306 object (i.e., one of the slots defined by the class's metaclass). Its
a888e3ac 307 VALUE must have the syntax of an initializer, and its consituent
1f1d88f5
MW
308 expressions must be constant expressions.
309
dea4d055 310 See `sod-initializer' for more details."))
1f1d88f5 311
dea4d055 312(export 'sod-instance-initializer)
1f1d88f5
MW
313(defclass sod-instance-initializer (sod-initializer)
314 ()
315 (:documentation
316 "Provides an initial value for a slot in all instances.
317
318 An instance slot initializer provides an initial value for a slot in
a888e3ac
MW
319 instances of the class. Its VALUE must have the syntax of an initializer.
320 Furthermore, if the slot has aggregate type, then you'd better be sure
321 that your compiler supports compound literals (6.5.2.5) because that's
322 what the initializer gets turned into.
1f1d88f5 323
dea4d055 324 See `sod-initializer' for more details."))
1f1d88f5
MW
325
326;;;--------------------------------------------------------------------------
327;;; Messages and methods.
abdf50aa 328
dea4d055 329(export '(sod-message sod-message-name sod-message-class sod-message-type))
abdf50aa 330(defclass sod-message ()
77027cca
MW
331 ((name :initarg :name :type string :reader sod-message-name)
332 (location :initarg :location :initform (file-location nil)
333 :type file-location :reader file-location)
4b8e5c03
MW
334 (%class :initarg :class :type sod-class :reader sod-message-class)
335 (%type :initarg :type :type c-function-type :reader sod-message-type))
abdf50aa 336 (:documentation
bf090e02 337 "Messages are the means for stimulating an object to behave.
abdf50aa
MW
338
339 SOD is a single-dispatch object system, like Smalltalk, C++, Python and so
340 on, but unlike CLOS and Dylan. Behaviour is invoked by `sending messages'
341 to objects. A message carries a name (distinguishing it from other
342 messages recognized by the same class), and a number of arguments; the
343 object may return a value in response. Sending a message therefore looks
344 very much like calling a function; indeed, each message bears the static
345 TYPE signature of a function.
346
347 An object reacts to being sent a message by executing an `effective
348 method', constructed from the direct methods defined on the recpient's
349 (run-time, not necessarily statically-declared) class and its superclasses
350 according to the message's `method combination'.
351
dea4d055 352 Much interesting work is done by subclasses of `sod-message', which (for
abdf50aa
MW
353 example) specify method combinations.
354
355 The slots are as follows.
356
357 * The NAME distinguishes the message from others defined by the same
358 class. Unlike most (all?) other object systems, messages defined in
359 different classes are in distinct namespaces. It is forbidden for a
360 message name to begin with an underscore, or to contain two
361 consecutive underscores. (Final underscores are fine.)
362
363 * The LOCATION states where in the user's source the slot was defined.
364 It gets used in error messages.
365
366 * The CLASS states which class defined the message.
367
368 * The TYPE is a function type describing the message's arguments and
369 return type.
370
371 Subclasses can (and probably will) define additional slots."))
372
1f1d88f5
MW
373(defmethod print-object ((message sod-message) stream)
374 (maybe-print-unreadable-object (message stream :type t)
375 (pprint-c-type (sod-message-type message) stream
376 (format nil "~A.~A"
377 (sod-class-nickname (sod-message-class message))
378 (sod-message-name message)))))
379
dea4d055
MW
380(export '(sod-method sod-method-message sod-method-class sod-method-type
381 sod-method-body))
abdf50aa 382(defclass sod-method ()
77027cca
MW
383 ((message :initarg :message :type sod-message :reader sod-method-message)
384 (location :initarg :location :initform (file-location nil)
385 :type file-location :reader file-location)
4b8e5c03
MW
386 (%class :initarg :class :type sod-class :reader sod-method-class)
387 (%type :initarg :type :type c-function-type :reader sod-method-type)
77027cca 388 (body :initarg :body :type (or c-fragment null) :reader sod-method-body))
abdf50aa
MW
389 (:documentation
390 "(Direct) methods are units of behaviour.
391
392 Methods are the unit of behaviour in SOD. Classes define direct methods
393 for particular messages.
394
395 When a message is received by an instance, all of the methods defined for
396 that message on that instance's (run-time, not static) class and its
397 superclasses are `applicable'. The applicable methods are gathered
398 together and invoked in some way; the details of this are left to the
dea4d055 399 `method combination', determined by the subclass of `sod-message'.
abdf50aa
MW
400
401 The slots are as follows.
402
403 * The MESSAGE describes which meessage invokes the method's behaviour.
404 The method is combined with other methods on the same message
405 according to the message's method combination, to form an `effective
406 method'.
407
408 * The LOCATION states where, in the user's source, the method was
409 defined. This gets used in error messages. (Depending on the user's
410 coding style, this location might be subtly different from the BODY's
411 location.)
412
413 * The CLASS specifies which class defined the method. This will be
414 either the class of the message, or one of its descendents.
415
416 * The TYPE gives the type of the method, including its arguments. This
417 will, in general, differ from the type of the message for several
418 reasons.
419
bf090e02
MW
420 -- The method type must include names for all of the method's
421 parameters. The message definition can omit the parameter
422 names (in the same way as a function declaration can). Formally,
423 the message definition can contain abstract declarators, whereas
424 method definitions must not.
abdf50aa
MW
425
426 -- Method combinations may require different parameter or return
bf090e02
MW
427 types. For example, `before' and `after' methods don't
428 contribute to the message's return value, so they must be defined
429 as returning `void'.
abdf50aa
MW
430
431 -- Method combinations may permit methods whose parameter and/or
bf090e02
MW
432 return types don't exactly match the corresponding types of the
433 message. For example, one might have methods with covariant
434 return types and contravariant parameter types. (This sounds
435 nice, but it doesn't actually seem like such a clever idea when
436 you consider that the co-/contravariance must hold among all the
437 applicable methods ordered according to the class precedence
438 list. As a result, a user might have to work hard to build
439 subclasses whose CPLs match the restrictions implied by the
440 method types.)
abdf50aa
MW
441
442 Method objects are fairly passive in the SOD translator. However,
dea4d055
MW
443 subclasses of `sod-message' may (and probably will) construct instances of
444 subclasses of `sod-method' in order to carry the additional metadata they
abdf50aa
MW
445 need to keep track of."))
446
1f1d88f5
MW
447(defmethod print-object ((method sod-method) stream)
448 (maybe-print-unreadable-object (method stream :type t)
449 (format stream "~A ~@_~A"
450 (sod-method-message method)
451 (sod-method-class method))))
abdf50aa 452
abdf50aa 453;;;----- That's all, folks --------------------------------------------------