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