Very ragged work-in-progress.
[sod] / class-defs.lisp
1 ;;; -*-lisp-*-
2 ;;;
3 ;;; Basic definitions for classes, methods and suchlike
4 ;;;
5 ;;; (c) 2009 Straylight/Edgeware
6 ;;;
7
8 ;;;----- Licensing notice ---------------------------------------------------
9 ;;;
10 ;;; This file is part of the Simple Object Definition system.
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 ;;; Classes.
30
31 (defclass sod-class ()
32 ((name :initarg :name
33 :type string
34 :reader sod-class-name)
35 (location :initarg :location
36 :initform (file-location nil)
37 :type file-location
38 :reader file-location)
39 (nickname :initarg :nick
40 :type string
41 :reader sod-class-nickname)
42 (direct-superclasses :initarg :superclasses
43 :type list
44 :reader sod-class-direct-superclasses)
45 (chain-link :initarg :link
46 :type (or sod-class null)
47 :reader sod-class-chain-link)
48 (metaclass :initarg :metaclass
49 :type sod-class
50 :reader sod-class-metaclass)
51 (slots :initarg :slots
52 :type list
53 :initform nil
54 :accessor sod-class-slots)
55 (instance-initializers :initarg :instance-initializers
56 :type list
57 :initform nil
58 :accessor sod-class-instance-initializers)
59 (class-initializers :initarg :class-initializers
60 :type list
61 :initform nil
62 :accessor sod-class-class-initializers)
63 (messages :initarg :messages
64 :type list
65 :initform nil
66 :accessor sod-class-messages)
67 (methods :initarg :methods
68 :type list
69 :initform nil
70 :accessor sod-class-methods)
71
72 (class-precedence-list :type list :accessor sod-class-precedence-list)
73
74 (chain-head :type sod-class :accessor sod-class-chain-head)
75 (chain :type list :accessor sod-class-chain)
76 (chains :type list :accessor sod-class-chains)
77
78 (ilayout :type ilayout :accessor sod-class-ilayout)
79 (effective-methods :type list :accessor sod-class-effective-methods)
80 (vtables :type list :accessor sod-class-vtables)
81
82 (state :initform nil
83 :type (member nil :finalized broken)
84 :accessor sod-class-state))
85 (:documentation
86 "Classes describe the layout and behaviour of objects.
87
88 The NAME, LOCATION, NICKNAME, DIRECT-SUPERCLASSES, CHAIN-LINK and
89 METACLASS slots are intended to be initialized when the class object is
90 constructed:
91
92 * The NAME is the identifier associated with the class in the user's
93 source file. It is used verbatim in the generated C code as a type
94 name, and must be distinct from other file-scope names in any source
95 file which includes the class definition. Furthermore, other names
96 are derived from the class name (most notably the class object
97 NAME__class), which have external linkage and must therefore be
98 distinct from all other identifiers in the program. It is forbidden
99 for a class NAME to begin with an underscore or to contain two
100 consecutive underscores.
101
102 * The LOCATION identifies where in the source the class was defined. It
103 gets used in error messages.
104
105 * The NICKNAME is a shorter identifier used to name the class in some
106 circumstances. The uniqueness requirements on NICKNAME are less
107 strict, which allows them to be shorter: no class may have two classes
108 with the same nickname on its class precedence list. Nicknames are
109 used (user-visibly) to distinguish slots and messages defined by
110 different classes, and (invisibly) in the derived names of direct
111 methods. It is forbidden for a nickname to begin with an underscore,
112 or to contain two consecutive underscores.
113
114 * The DIRECT-SUPERCLASSES are a list of the class's direct superclasses,
115 in the order that they were declared in the source. The class
116 precedence list is computed from the DIRECT-SUPERCLASSES lists of all
117 of the superclasses involved.
118
119 * The CHAIN-LINK is either NIL or one of the DIRECT-SUPERCLASSES. Class
120 chains are a means for recovering most of the benefits of simple
121 hierarchy lost by the introduction of multiple inheritance. A class's
122 superclasses (including itself) are partitioned into chains,
123 consisting of a class, its CHAIN-LINK superclass, that class's
124 CHAIN-LINK, and so on. It is an error if two direct subclasses of any
125 class appear in the same chain (a global property which requires
126 global knowledge of an entire program's class hierarchy in order to
127 determine sensibly). Slots of superclasses in the same chain can be
128 accessed efficiently; there is an indirection needed to access slots
129 of superclasses in other chains. Furthermore, an indirection is
130 required to perform a cross-chain conversion (i.e., converting a
131 pointer to an instance of some class into a pointer to an instance of
132 one of its superclasses in a different chain), an operation which
133 occurs implicitly in effective methods in order to call direct methods
134 defined on cross-chain superclasses.
135
136 * The METACLASS is the class of the class object. Classes are objects
137 in their own right, and therefore must be instances of some class;
138 this class is the metaclass. Metaclasses can define additional slots
139 and methods to be provided by their instances; a class definition can
140 provide (C constant expression) initial values for the metaclass
141 instance.
142
143 The next few slots can't usually be set at object-construction time, since
144 the objects need to contain references to the class object itself.
145
146 * The SLOTS are a list of the slots defined by the class (instances of
147 SOD-SLOT). (The class will also define all of the slots defined by
148 its superclasses.)
149
150 * The INSTANCE-INITIALIZERS and CLASS-INITIALIZERS are lists of
151 initializers for slots (see SOD-INITIALIZER and subclasses), providing
152 initial values for instances of the class, and for the class's class
153 object itself, respectively.
154
155 * The MESSAGES are a list of the messages recognized by the class
156 (instances of SOD-MESSAGE and subclasses). (Note that the message
157 need not have any methods defined on it. The class will also
158 recognize all of the messages defined by its superclasses.)
159
160 * The METHODS are a list of (direct) methods defined on the class
161 (instances of SOD-METHOD and subclasses). Each method provides
162 behaviour to be invoked by a particular message recognized by the
163 class.
164
165 Other slots are computed from these in order to describe the class's
166 layout and effective methods; this is done by FINALIZE-SOD-CLASS.
167
168 * The CLASS-PRECEDENCE-LIST is a list of superclasses in a linear order.
169 It is computed by the generic function COMPUTE-CLASS-PRECEDENCE-LIST,
170 whose default implementation ensures that the order of superclasses is
171 such that (a) subclasses appear before their superclasses; (b) the
172 direct superclasses of a given class appear in the order in which they
173 were declared by the programmer; and (c) classes always appear in the
174 same relative order in all class precedence lists in the same
175 superclass graph.
176
177 * The CHAIN-HEAD is the least-specific class in the class's chain. If
178 there is no link class then the CHAIN-HEAD is the class itself. This
179 slot, like the next two, is computed by the generic function
180 COMPUTE-CHAINS.
181
182 * The CHAIN is the list of classes on the complete primary chain,
183 starting from this class and ending with the CHAIN-HEAD.
184
185 * The CHAINS are the complete collection of chains (most-to-least
186 specific) for the class and all of its superclasses.
187
188 * The ILAYOUT describes the layout for an instance of the class. It's
189 quite complicated; see the documentation of the ILAYOUT class for
190 detais.
191
192 * The EFFECTIVE-METHODS are a list of effective methods, specialized for
193 the class.
194
195 * The VTABLES are a list of descriptions of vtables for the class. The
196 individual elements are VTABLE objects, which are even more
197 complicated than ILAYOUT structures. See the class documentation for
198 details."))
199
200 (defmethod print-object ((class sod-class) stream)
201 (maybe-print-unreadable-object (class stream :type t)
202 (princ (sod-class-name class) stream)))
203
204 ;;;--------------------------------------------------------------------------
205 ;;; Slots and initializers.
206
207 (defclass sod-slot ()
208 ((name :initarg :name
209 :type string
210 :reader sod-slot-name)
211 (location :initarg :location
212 :initform (file-location nil)
213 :type file-location
214 :reader file-location)
215 (class :initarg :class
216 :type sod-class
217 :reader sod-slot-class)
218 (type :initarg :type
219 :type c-type
220 :reader sod-slot-type))
221 (:documentation
222 "Slots are units of information storage in instances.
223
224 Each class defines a number of slots, which function similarly to (data)
225 members in structures. An instance contains all of the slots defined in
226 its class and all of its superclasses.
227
228 A slot carries the following information.
229
230 * A NAME, which distinguishes it from other slots defined by the same
231 class. Unlike most (all?) other object systems, slots defined in
232 different classes are in distinct namespaces. There are no special
233 restrictions on slot names.
234
235 * A LOCATION, which states where in the user's source the slot was
236 defined. This gets used in error messages.
237
238 * A CLASS, which states which class defined the slot. The slot is
239 available in instances of this class and all of its descendents.
240
241 * A TYPE, which is the C type of the slot. This must be an object type
242 (certainly not a function type, and it must be a complete type by the
243 time that the user header code has been scanned)."))
244
245 (defmethod print-object ((slot sod-slot) stream)
246 (maybe-print-unreadable-object (slot stream :type t)
247 (pprint-c-type (sod-slot-type slot) stream
248 (format nil "~A.~A"
249 (sod-class-nickname (sod-slot-class slot))
250 (sod-slot-name slot)))))
251
252 (defclass sod-initializer ()
253 ((slot :initarg :slot
254 :type sod-slot
255 :reader sod-initializer-slot)
256 (location :initarg :location
257 :initform (file-location nil)
258 :type file-location
259 :reader file-location)
260 (class :initarg :class
261 :type sod-class
262 :reader sod-initializer-clas)
263 (value-kind :initarg :value-kind
264 :type keyword
265 :reader sod-initializer-value-kind)
266 (value-form :initarg :value-form
267 :type c-fragment
268 :reader sod-initializer-value-form))
269 (:documentation
270 "Provides an initial value for a slot.
271
272 The slots of an initializer are as follows.
273
274 * The SLOT specifies which slot this initializer is meant to initialize.
275
276 * The LOCATION states the position in the user's source file where the
277 initializer was found. This gets used in error messages. (Depending
278 on the source layout style, this might differ from the location in the
279 VALUE-FORM C fragment.)
280
281 * The CLASS states which class defined this initializer. For instance
282 slot initializers (SOD-INSTANCE-INITIALIZER), this will be the same as
283 the SLOT's class, or be one of its descendants. For class slot
284 initializers (SOD-CLASS-INITIALIZER), this will be an instance of the
285 SLOT's class, or an instance of one of its descendants.
286
287 * The VALUE-KIND states what manner of initializer we have. It can be
288 either :SINGLE, indicating a standalone expression, or :COMPOUND,
289 indicating a compound initializer which must be surrounded by braces
290 on output.
291
292 * The VALUE-FORM gives the text of the initializer, as a C fragment.
293
294 Typically you'll see instances of subclasses of this class in the wild
295 rather than instances of this class directly. See SOD-CLASS-INITIALIZER
296 and SOD-INSTANCE-INITIALIZER."))
297
298 (defmethod print-object ((initializer sod-initializer) stream)
299 (if *print-escape*
300 (print-unreadable-object (initializer stream :type t)
301 (format stream "~A = ~A"
302 (sod-initializer-slot initializer)
303 initializer))
304 (format stream "~:[{~A}~;~A~]"
305 (eq (sod-initializer-value-kind initializer) :single)
306 (sod-initializer-value-form initializer))))
307
308 (defclass sod-class-initializer (sod-initializer)
309 ()
310 (:documentation
311 "Provides an initial value for a class slot.
312
313 A class slot initializer provides an initial value for a slot in the class
314 object (i.e., one of the slots defined by the class's metaclass). Its
315 VALUE-FORM must have the syntax of an initializer, and its consituent
316 expressions must be constant expressions.
317
318 See SOD-INITIALIZER for more details."))
319
320 (defclass sod-instance-initializer (sod-initializer)
321 ()
322 (:documentation
323 "Provides an initial value for a slot in all instances.
324
325 An instance slot initializer provides an initial value for a slot in
326 instances of the class. Its VALUE-FORM must have the syntax of an
327 initializer. Furthermore, if the slot has aggregate type, then you'd
328 better be sure that your compiler supports compound literals (6.5.2.5)
329 because that's what the initializer gets turned into.
330
331 See SOD-INITIALIZER for more details."))
332
333 ;;;--------------------------------------------------------------------------
334 ;;; Messages and methods.
335
336 (defclass sod-message ()
337 ((name :initarg :name
338 :type string
339 :reader sod-message-name)
340 (location :initarg :location
341 :initform (file-location nil)
342 :type file-location
343 :reader file-location)
344 (class :initarg :class
345 :type sod-class
346 :reader sod-message-class)
347 (type :initarg :type
348 :type c-function-type
349 :reader sod-message-type))
350 (:documentation
351 "Messages the means for stimulating an object to behave.
352
353 SOD is a single-dispatch object system, like Smalltalk, C++, Python and so
354 on, but unlike CLOS and Dylan. Behaviour is invoked by `sending messages'
355 to objects. A message carries a name (distinguishing it from other
356 messages recognized by the same class), and a number of arguments; the
357 object may return a value in response. Sending a message therefore looks
358 very much like calling a function; indeed, each message bears the static
359 TYPE signature of a function.
360
361 An object reacts to being sent a message by executing an `effective
362 method', constructed from the direct methods defined on the recpient's
363 (run-time, not necessarily statically-declared) class and its superclasses
364 according to the message's `method combination'.
365
366 Much interesting work is done by subclasses of SOD-MESSAGE, which (for
367 example) specify method combinations.
368
369 The slots are as follows.
370
371 * The NAME distinguishes the message from others defined by the same
372 class. Unlike most (all?) other object systems, messages defined in
373 different classes are in distinct namespaces. It is forbidden for a
374 message name to begin with an underscore, or to contain two
375 consecutive underscores. (Final underscores are fine.)
376
377 * The LOCATION states where in the user's source the slot was defined.
378 It gets used in error messages.
379
380 * The CLASS states which class defined the message.
381
382 * The TYPE is a function type describing the message's arguments and
383 return type.
384
385 Subclasses can (and probably will) define additional slots."))
386
387 (defmethod print-object ((message sod-message) stream)
388 (maybe-print-unreadable-object (message stream :type t)
389 (pprint-c-type (sod-message-type message) stream
390 (format nil "~A.~A"
391 (sod-class-nickname (sod-message-class message))
392 (sod-message-name message)))))
393
394 (defclass sod-method ()
395 ((message :initarg :message
396 :type sod-message
397 :reader sod-method-message)
398 (location :initarg :location
399 :initform (file-location nil)
400 :type file-location
401 :reader file-location)
402 (class :initarg :class
403 :type sod-class
404 :reader sod-method-class)
405 (type :initarg :type
406 :type c-function-type
407 :reader sod-method-type)
408 (body :initarg :body
409 :type (or c-fragment null)
410 :reader sod-method-body))
411 (:documentation
412 "(Direct) methods are units of behaviour.
413
414 Methods are the unit of behaviour in SOD. Classes define direct methods
415 for particular messages.
416
417 When a message is received by an instance, all of the methods defined for
418 that message on that instance's (run-time, not static) class and its
419 superclasses are `applicable'. The applicable methods are gathered
420 together and invoked in some way; the details of this are left to the
421 `method combination', determined by the subclass of SOD-MESSAGE.
422
423 The slots are as follows.
424
425 * The MESSAGE describes which meessage invokes the method's behaviour.
426 The method is combined with other methods on the same message
427 according to the message's method combination, to form an `effective
428 method'.
429
430 * The LOCATION states where, in the user's source, the method was
431 defined. This gets used in error messages. (Depending on the user's
432 coding style, this location might be subtly different from the BODY's
433 location.)
434
435 * The CLASS specifies which class defined the method. This will be
436 either the class of the message, or one of its descendents.
437
438 * The TYPE gives the type of the method, including its arguments. This
439 will, in general, differ from the type of the message for several
440 reasons.
441
442 -- Firstly, the method type must include names for all of the
443 method's parameters. The message definition can omit the
444 parameter names (in the same way as a function declaration can).
445 Formally, the message definition can contain abstract
446 declarators, whereas method definitions must not.
447
448 -- Method combinations may require different parameter or return
449 types. For example, `before' and `after' methods don't
450 contribute to the message's return value, so they must be defined
451 as returning `void'.
452
453 -- Method combinations may permit methods whose parameter and/or
454 return types don't exactly match the corresponding types of the
455 message. For example, one might have methods with covariant
456 return types and contravariant parameter types. (This sounds
457 nice, but it doesn't actually seem like such a clever idea when
458 you consider that the co-/contravariance must hold among all the
459 applicable methods ordered according to the class precedence
460 list. As a result, a user might have to work hard to build
461 subclasses whose CPLs match the restrictions implied by the
462 method types.)
463
464 Method objects are fairly passive in the SOD translator. However,
465 subclasses of SOD-MESSAGE may (and probably will) construct instances of
466 subclasses of SOD-METHOD in order to carry the additional metadata they
467 need to keep track of."))
468
469 (defmethod print-object ((method sod-method) stream)
470 (maybe-print-unreadable-object (method stream :type t)
471 (format stream "~A ~@_~A"
472 (sod-method-message method)
473 (sod-method-class method))))
474
475 ;;;--------------------------------------------------------------------------
476 ;;; Classes as C types.
477
478 (defclass c-class-type (simple-c-type)
479 ((class :initarg :class
480 :type (or null sod-class)
481 :accessor c-type-class))
482 (:documentation
483 "A SOD class, as a C type.
484
485 One usually handles classes as pointers, but the type refers to the actual
486 instance structure itself. Or, in fact, just the primary chain of the
487 instance (i.e., the one containing the class's own direct slots) -- which
488 is why dealing with the instance structure directly doesn't make much
489 sense.
490
491 The CLASS slot will be NIL if the class isn't defined yet, i.e., this
492 entry was constructed by a forward reference operation.
493
494 The NAME slot inherited from SIMPLE-C-TYPE is here so that we can print
495 the type even when it's a forward reference."))
496
497 (defmethod c-type-equal-p and ((type-a c-class-type)
498 (type-b c-class-type))
499 (eql (c-type-class type-a) (c-type-class type-b)))
500
501 (defmethod print-c-type (stream (type c-class-type) &optional colon atsign)
502 (declare (ignore colon atsign))
503 (format stream "~:@<CLASS ~@_~S~{ ~_~S~}~:>"
504 (c-type-name type)
505 (c-type-qualifiers type)))
506
507 (defun find-class-type (name &optional floc)
508 "Look up NAME and return the corresponding C-CLASS-TYPE.
509
510 Returns two values: TYPE and WINP.
511
512 * If the type was found, and was a class, returns TYPE.
513
514 * If no type was found at all, returns NIL.
515
516 * If a type was found, but it wasn't a class, signals an error at FLOC."
517
518 (with-default-error-location (floc)
519 (let ((type (gethash name *type-map*)))
520 (typecase type
521 (null nil)
522 (c-class-type type)
523 (t (error "Type `~A' (~A) is not a class" name type))))))
524
525 (defun make-class-type (name &optional floc)
526 "Return a class type for NAME, creating it if necessary.
527
528 FLOC is the location to use in error reports."
529 (let ((name (etypecase name
530 (sod-class (sod-class-name name))
531 (string name))))
532 (or (find-class-type name floc)
533 (setf (gethash name *type-map*)
534 (make-instance 'c-class-type :name name :class nil)))))
535
536 (defun find-sod-class (name &optional floc)
537 "Return the SOD-CLASS object with the given NAME.
538
539 FLOC is the location to use in error reports."
540 (with-default-error-location (floc)
541 (let ((type (find-class-type name floc)))
542 (cond ((not type) (error "Type `~A' not known" name))
543 (t (let ((class (c-type-class type)))
544 (unless class
545 (error "Class `~A' is incomplete" name))
546 class))))))
547
548 (defun record-sod-class (class &optional (floc class))
549 "Record CLASS as being a class definition.
550
551 FLOC is the location to use in error reports."
552 (with-default-error-location (floc)
553 (let* ((name (sod-class-name class))
554 (type (make-class-type name floc)))
555 (cond ((null type) nil)
556 ((c-type-class type)
557 (cerror* "Class `~A' already defined at ~A"
558 name (file-location (c-type-class type))))
559 (t
560 (setf (c-type-class type) class))))))
561
562 (defun sod-class-type (class)
563 "Returns the C type corresponding to CLASS."
564 (find-class-type (sod-class-name class)))
565
566 (define-c-type-syntax class (name &rest quals)
567 "Returns a type object for the named class."
568 (if quals
569 `(qualify-type (make-class-type ,name) (list ,@quals))
570 `(make-class-type ,name)))
571
572 ;;;----- That's all, folks --------------------------------------------------