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