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