implementation of C89. Initializers will be evaluated once each time an
instance is initialized.
+Slots are initialized in reverse-precedence order of their defining classes;
+i.e., slots defined by a less specific superclass are initialized earlier
+than slots defined by a more specific superclass. Slots defined by the same
+class are initialized in the order in which they appear in the class
+definition.
+
+The initializer for a slot may refer to other slots in the same object, via
+the @|me| pointer: in an initializer for a slot defined by a class $C$, @|me|
+has type `pointer to $C$'. (Note that the type of @|me| depends only on the
+class which defined the slot, not the class which defined the initializer.)
+
\subsection{C language integration} \label{sec:concepts.classes.c}
method calls on its @|next_method| more than once, unless some other method
takes steps to prevent this.
+Slots are initialized in a well-defined order.
+\begin{itemize}
+\item Slots defined by a more specific superclasses are initialized after
+ slots defined by a less specific superclass.
+\item Slots defined by the same class are initialized in the order in which
+ their definitions appear.
+\end{itemize}
+
The recommended way to add new initialization behaviour is to define @|after|
methods on the @|init| message. These will be run after the slot
initializers have been applied, in reverse precedence order.
codegen
target))))
+;; Utilities.
+
+(defun declare-me (codegen class)
+ "Emit, to CODEGEN, a declaration of `me' as a pointer to CLASS.
+
+ The pointer refers to a part of the prevailing `sod__obj' object, which is
+ assumed to be a pointer to an appropriate `ilayout' structure."
+ (emit-decl codegen (make-var-inst "me" (c-type (* (class class)))
+ (format nil "&sod__obj->~A.~A"
+ (sod-class-nickname
+ (sod-class-chain-head class))
+ (sod-class-nickname class)))))
+
;; Initialization.
(defclass initialization-message (lifecycle-message)
(deliver-expr codegen var *sod-tmp-val*)
(codegen-pop-block codegen)))
- ;; Loop over the instance layout emitting initializers as we find them.
- (dolist (ichain (ilayout-ichains ilayout))
- (let ((ich (format nil "sod__obj->~A.~A"
- (sod-class-nickname (ichain-head ichain))
- (sod-class-nickname (ichain-tail ichain)))))
- (dolist (item (ichain-body ichain))
- (etypecase item
- (vtable-pointer
- nil)
- (islots
- (let ((isl (format nil "~A.~A"
- ich
- (sod-class-nickname (islots-class item)))))
- (dolist (slot (islots-slots item))
- (let ((dslot (effective-slot-direct-slot slot))
- (init (effective-slot-initializer slot)))
- (when init
- (let* ((slot-type (sod-slot-type dslot))
- (slot-default (sod-initializer-value init))
- (target (format nil "~A.~A"
- isl (sod-slot-name dslot)))
- (initinst (set-from-initializer target
- slot-type
- slot-default)))
- (emit-inst codegen initinst))))))))))))
+ ;; Initialize the structure defined by the various superclasses, in
+ ;; reverse precedence order.
+ (dolist (super (reverse (sod-class-precedence-list class)))
+ (let* ((ichain (find (sod-class-chain-head super)
+ (ilayout-ichains ilayout)
+ :key #'ichain-head))
+ (islots (find super (ichain-body ichain)
+ :test (lambda (class item)
+ (and (typep item 'islots)
+ (eq (islots-class item) class)))))
+ (this-class-focussed-p nil)
+ (isl (format nil "me->~A" (sod-class-nickname super))))
+
+ (flet ((focus-this-class ()
+ ;; Delayed initial preparation. Don't bother defining the
+ ;; `me' pointer if there's actually nothing to do.
+ (unless this-class-focussed-p
+ (emit-banner codegen
+ "Initialization for class `~A'." super)
+ (codegen-push codegen)
+ (declare-me codegen super)
+ (setf this-class-focussed-p t))))
+
+ ;; Work through each slot in turn.
+ (dolist (slot (and islots (islots-slots islots)))
+ (let ((dslot (effective-slot-direct-slot slot))
+ (init (effective-slot-initializer slot)))
+ (when init
+ (focus-this-class)
+ (let* ((slot-type (sod-slot-type dslot))
+ (slot-default (sod-initializer-value init))
+ (target (format nil "~A.~A"
+ isl (sod-slot-name dslot)))
+ (initinst (set-from-initializer target
+ slot-type
+ slot-default)))
+ (emit-inst codegen initinst)))))
+
+ ;; If we opened a block to initialize this class then close it
+ ;; again.
+ (when this-class-focussed-p
+ (emit-inst codegen (codegen-pop-block codegen)))))))
;; Done making the initialization function.
(codegen-pop-function codegen func-name func-type