chiark / gitweb /
src/final.lisp: Add function for interactively testing type parsing.
[sod] / src / class-output.lisp
CommitLineData
1f1d88f5
MW
1;;; -*-lisp-*-
2;;;
dea4d055 3;;; Output for classes
1f1d88f5
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.
1f1d88f5
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
6e2d4b52
MW
28;;;--------------------------------------------------------------------------
29;;; Walking the layout tree.
30
31(defmethod hook-output progn ((class sod-class) reason sequencer)
32 (with-slots ((ilayout %ilayout) vtables methods effective-methods) class
33 (hook-output ilayout reason sequencer)
34 (dolist (method methods) (hook-output method reason sequencer))
35 (dolist (method effective-methods) (hook-output method reason sequencer))
36 (dolist (vtable vtables) (hook-output vtable reason sequencer))))
37
38(defmethod hook-output progn ((ilayout ilayout) reason sequencer)
39 (with-slots (ichains) ilayout
40 (dolist (ichain ichains) (hook-output ichain reason sequencer))))
41
42(defmethod hook-output progn ((ichain ichain) reason sequencer)
1224dfb0 43 (dolist (item (ichain-body ichain)) (hook-output item reason sequencer)))
6e2d4b52
MW
44
45(defmethod hook-output progn ((islots islots) reason sequencer)
1224dfb0 46 (dolist (slot (islots-slots islots)) (hook-output slot reason sequencer)))
6e2d4b52
MW
47
48(defmethod hook-output progn ((vtable vtable) reason sequencer)
49 (with-slots (body) vtable
50 (dolist (item body) (hook-output item reason sequencer))))
51
52(defmethod hook-output progn ((vtmsgs vtmsgs) reason sequencer)
53 (with-slots (entries) vtmsgs
54 (dolist (entry entries) (hook-output entry reason sequencer))))
55
1f1d88f5
MW
56;;;--------------------------------------------------------------------------
57;;; Classes.
58
5b0a2bdb 59(defmethod hook-output progn ((class sod-class) (reason (eql :h)) sequencer)
1f1d88f5
MW
60
61 ;; Main output sequencing.
62 (sequence-output (stream sequencer)
63
1f1d88f5
MW
64 :constraint
65 ((:classes :start)
66 (class :banner)
67 (class :islots :start) (class :islots :slots) (class :islots :end)
68 (class :vtmsgs :start) (class :vtmsgs :end)
69 (class :vtables :start) (class :vtables :end)
70 (class :vtable-externs) (class :vtable-externs-after)
ddee4bb1 71 (class :methods :start) (class :methods) (class :methods :end)
1f1d88f5
MW
72 (class :ichains :start) (class :ichains :end)
73 (class :ilayout :start) (class :ilayout :slots) (class :ilayout :end)
74 (class :conversions)
6bc944c3 75 (class :message-macros)
ddee4bb1 76 (class :object)
1f1d88f5
MW
77 (:classes :end))
78
79 (:typedefs
80 (format stream "typedef struct ~A ~A;~%"
81 (ichain-struct-tag class (sod-class-chain-head class)) class))
82
83 ((class :banner)
84 (banner (format nil "Class ~A" class) stream))
85 ((class :vtable-externs-after)
ddee4bb1
MW
86 (terpri stream))
87
88 ((class :vtable-externs)
89 (format stream "/* Vtable structures. */~%"))
90
91 ((class :object)
92 (let ((metaclass (sod-class-metaclass class))
93 (metaroot (find-root-metaclass class)))
a07d8d00
MW
94 (format stream "/* The class object. */~@
95 extern const struct ~A ~A__classobj;~@
ddee4bb1
MW
96 #define ~:*~A__class (&~:*~A__classobj.~A.~A)~2%"
97 (ilayout-struct-tag metaclass) class
98 (sod-class-nickname (sod-class-chain-head metaroot))
99 (sod-class-nickname metaroot)))))
1f1d88f5
MW
100
101 ;; Maybe generate an islots structure.
102 (when (sod-class-slots class)
103 (dolist (slot (sod-class-slots class))
dea4d055 104 (hook-output slot 'islots sequencer))
1f1d88f5
MW
105 (sequence-output (stream sequencer)
106 ((class :islots :start)
a07d8d00 107 (format stream "/* Instance slots. */~@
ddee4bb1
MW
108 struct ~A {~%"
109 (islots-struct-tag class)))
1f1d88f5
MW
110 ((class :islots :end)
111 (format stream "};~2%"))))
112
113 ;; Declare the direct methods.
114 (when (sod-class-methods class)
1f1d88f5 115 (sequence-output (stream sequencer)
ddee4bb1
MW
116 ((class :methods :start)
117 (format stream "/* Direct methods. */~%"))
118 ((class :methods :end)
1f1d88f5
MW
119 (terpri stream))))
120
121 ;; Provide upcast macros which do the right thing.
122 (when (sod-class-direct-superclasses class)
123 (sequence-output (stream sequencer)
124 ((class :conversions)
125 (let ((chain-head (sod-class-chain-head class)))
ddee4bb1 126 (format stream "/* Conversion macros. */~%")
1f1d88f5
MW
127 (dolist (super (cdr (sod-class-precedence-list class)))
128 (let ((super-head (sod-class-chain-head super)))
bb172d53
MW
129 (format stream "#define ~:@(~A__CONV_~A~)(_obj) ((~A *)~
130 ~:[SOD_XCHAIN(~A, (_obj))~;(_obj)~])~%"
1f1d88f5
MW
131 class (sod-class-nickname super) super
132 (eq chain-head super-head)
ddee4bb1
MW
133 (sod-class-nickname super-head))))
134 (terpri stream)))))
1f1d88f5 135
6bc944c3
MW
136 ;; Provide convenience macros for sending the newly defined messages. (The
137 ;; macros work on all subclasses too.)
138 ;;
139 ;; We need each message's method entry type for this, so we need to dig it
140 ;; out of the vtmsgs structure. Indeed, the vtmsgs for this class contains
141 ;; entries for precisely the messages we want to make macros for.
e674612e
MW
142 (when (some #'varargs-message-p (sod-class-messages class))
143 (one-off-output 'varargs-macros sequencer :early-decls
144 (lambda (stream)
145 (format stream
146 "~%SOD__VARARGS_MACROS_PREAMBLE~%"))))
6bc944c3
MW
147 (when (sod-class-messages class)
148 (sequence-output (stream sequencer)
149 ((class :message-macros)
150 (let* ((vtable (find (sod-class-chain-head class)
151 (sod-class-vtables class)
152 :key #'vtable-chain-head))
153 (vtmsgs (find-if (lambda (item)
154 (and (typep item 'vtmsgs)
155 (eql (vtmsgs-class item) class)))
156 (vtable-body vtable))))
157 (format stream "/* Message invocation macros. */~%")
6bc944c3
MW
158 (dolist (entry (vtmsgs-entries vtmsgs))
159 (let* ((type (method-entry-function-type entry))
160 (args (c-function-arguments type))
6bc944c3
MW
161 (in-names nil) (out-names nil) (varargsp nil) (me "me"))
162 (do ((args args (cdr args)))
163 ((endp args))
b426ab51 164 (let* ((raw-name (princ-to-string (argument-name (car args))))
6bc944c3
MW
165 (name (if (find raw-name
166 (list "_vt"
167 (sod-class-nickname class)
b426ab51 168 (method-entry-slot-name entry))
6bc944c3
MW
169 :test #'string=)
170 (format nil "sod__a_~A" raw-name)
171 raw-name)))
172 (cond ((and (cdr args) (eq (cadr args) :ellipsis))
173 (setf varargsp t)
68a4f8c9 174 (unless in-names (setf me "SOD__CAR(__VA_ARGS__)"))
6bc944c3
MW
175 (push (format nil "/*~A*/ ..." name) in-names)
176 (push "__VA_ARGS__" out-names)
177 (return))
178 (t
179 (push name in-names)
180 (push name out-names)))))
181 (when varargsp
e674612e 182 (format stream "#ifdef SOD__HAVE_VARARGS_MACROS~%"))
6bc944c3
MW
183 (format stream "#define ~A(~{~A~^, ~}) ~
184 ~A->_vt->~A.~A(~{~A~^, ~})~%"
b426ab51 185 (message-macro-name class entry)
6bc944c3
MW
186 (nreverse in-names)
187 me
188 (sod-class-nickname class)
b426ab51 189 (method-entry-slot-name entry)
6bc944c3
MW
190 (nreverse out-names))
191 (when varargsp
192 (format stream "#endif~%"))))
193 (terpri stream)))))
194
1f1d88f5 195 ;; Generate vtmsgs structure for all superclasses.
6e2d4b52 196 (hook-output (car (sod-class-vtables class)) 'vtmsgs sequencer))
1f1d88f5
MW
197
198;;;--------------------------------------------------------------------------
199;;; Instance structure.
200
1224dfb0
MW
201(defmethod hook-output progn
202 ((slot sod-slot) (reason (eql 'islots)) sequencer)
1f1d88f5
MW
203 (sequence-output (stream sequencer)
204 (((sod-slot-class slot) :islots :slots)
205 (pprint-logical-block (stream nil :prefix " " :suffix ";")
206 (pprint-c-type (sod-slot-type slot) stream (sod-slot-name slot)))
207 (terpri stream))))
208
5b0a2bdb 209(defmethod hook-output progn ((ilayout ilayout) (reason (eql :h)) sequencer)
4b8e5c03 210 (with-slots ((class %class) ichains) ilayout
1f1d88f5
MW
211 (sequence-output (stream sequencer)
212 ((class :ilayout :start)
a07d8d00 213 (format stream "/* Instance layout. */~@
ddee4bb1
MW
214 struct ~A {~%"
215 (ilayout-struct-tag class)))
1f1d88f5
MW
216 ((class :ilayout :end)
217 (format stream "};~2%")))
218 (dolist (ichain ichains)
dea4d055 219 (hook-output ichain 'ilayout sequencer))))
1f1d88f5 220
5b0a2bdb 221(defmethod hook-output progn ((ichain ichain) (reason (eql :h)) sequencer)
4b8e5c03 222 (with-slots ((class %class) chain-head chain-tail) ichain
ddee4bb1
MW
223 (when (eq class chain-tail)
224 (sequence-output (stream sequencer)
225 :constraint ((class :ichains :start)
226 (class :ichain chain-head :start)
227 (class :ichain chain-head :slots)
228 (class :ichain chain-head :end)
229 (class :ichains :end))
230 ((class :ichain chain-head :start)
a07d8d00 231 (format stream "/* Instance chain structure. */~@
ddee4bb1
MW
232 struct ~A {~%"
233 (ichain-struct-tag chain-tail chain-head)))
234 ((class :ichain chain-head :end)
235 (format stream "};~2%")
a07d8d00
MW
236 (format stream "/* Union of equivalent superclass chains. */~@
237 union ~A {~@
ddee4bb1
MW
238 ~:{ struct ~A ~A;~%~}~
239 };~2%"
240 (ichain-union-tag chain-tail chain-head)
dea4d055
MW
241
242 ;; Make sure the most specific class is first: only the
243 ;; first element of a union can be statically initialized in
244 ;; C90.
ddee4bb1
MW
245 (mapcar (lambda (super)
246 (list (ichain-struct-tag super chain-head)
247 (sod-class-nickname super)))
248 (sod-class-chain chain-tail))))))))
1f1d88f5 249
1224dfb0
MW
250(defmethod hook-output progn
251 ((ichain ichain) (reason (eql 'ilayout)) sequencer)
4b8e5c03 252 (with-slots ((class %class) chain-head chain-tail) ichain
1f1d88f5
MW
253 (sequence-output (stream sequencer)
254 ((class :ilayout :slots)
ddee4bb1
MW
255 (format stream " union ~A ~A;~%"
256 (ichain-union-tag chain-tail chain-head)
1f1d88f5
MW
257 (sod-class-nickname chain-head))))))
258
5b0a2bdb
MW
259(defmethod hook-output progn ((vtptr vtable-pointer)
260 (reason (eql :h))
261 sequencer)
4b8e5c03 262 (with-slots ((class %class) chain-head chain-tail) vtptr
64fd357d
MW
263 (when (eq class chain-tail)
264 (sequence-output (stream sequencer)
265 ((class :ichain chain-head :slots)
266 (format stream " const struct ~A *_vt;~%"
267 (vtable-struct-tag chain-tail chain-head)))))))
1f1d88f5 268
5b0a2bdb 269(defmethod hook-output progn ((islots islots) (reason (eql :h)) sequencer)
4b8e5c03 270 (with-slots ((class %class) subclass slots) islots
64fd357d
MW
271 (let ((head (sod-class-chain-head class)))
272 (when (eq head (sod-class-chain-head subclass))
273 (sequence-output (stream sequencer)
274 ((subclass :ichain (sod-class-chain-head class) :slots)
275 (format stream " struct ~A ~A;~%"
276 (islots-struct-tag class)
277 (sod-class-nickname class))))))))
1f1d88f5
MW
278
279;;;--------------------------------------------------------------------------
280;;; Vtable structure.
281
1224dfb0
MW
282(defmethod hook-output progn
283 ((method sod-method) (reason (eql :h)) sequencer)
4b8e5c03 284 (with-slots ((class %class)) method
ddee4bb1
MW
285 (sequence-output (stream sequencer)
286 ((class :methods)
287 (let ((type (sod-method-function-type method)))
288 (princ "extern " stream)
289 (pprint-c-type (commentify-function-type type) stream
290 (sod-method-function-name method))
291 (format stream ";~%"))))))
292
5b0a2bdb 293(defmethod hook-output progn ((vtable vtable) (reason (eql :h)) sequencer)
4b8e5c03 294 (with-slots ((class %class) chain-head chain-tail) vtable
ddee4bb1
MW
295 (when (eq class chain-tail)
296 (sequence-output (stream sequencer)
297 :constraint ((class :vtables :start)
298 (class :vtable chain-head :start)
299 (class :vtable chain-head :slots)
300 (class :vtable chain-head :end)
301 (class :vtables :end))
302 ((class :vtable chain-head :start)
a07d8d00 303 (format stream "/* Vtable structure. */~@
ddee4bb1
MW
304 struct ~A {~%"
305 (vtable-struct-tag chain-tail chain-head)))
306 ((class :vtable chain-head :end)
c2438e62
MW
307 (format stream "};~2%")
308 (format stream "/* Union of equivalent superclass vtables. */~@
309 union ~A {~@
310 ~:{ struct ~A ~A;~%~}~
311 };~2%"
312 (vtable-union-tag chain-tail chain-head)
313
314 ;; As for the ichain union, make sure the most specific
315 ;; class is first.
316 (mapcar (lambda (super)
317 (list (vtable-struct-tag super chain-head)
318 (sod-class-nickname super)))
319 (sod-class-chain chain-tail))))))
1f1d88f5 320 (sequence-output (stream sequencer)
1f1d88f5 321 ((class :vtable-externs)
7c3bae74 322 (format stream "~@<extern const union ~A ~2I~_~A;~:>~%"
c2438e62 323 (vtable-union-tag chain-tail chain-head)
7c3bae74 324 (vtable-name class chain-head))))))
1f1d88f5 325
5b0a2bdb 326(defmethod hook-output progn ((vtmsgs vtmsgs) (reason (eql :h)) sequencer)
4b8e5c03 327 (with-slots ((class %class) subclass chain-head chain-tail) vtmsgs
64fd357d
MW
328 (when (eq subclass chain-tail)
329 (sequence-output (stream sequencer)
330 ((subclass :vtable chain-head :slots)
331 (format stream " struct ~A ~A;~%"
332 (vtmsgs-struct-tag subclass class)
333 (sod-class-nickname class)))))))
1f1d88f5 334
1224dfb0
MW
335(defmethod hook-output progn
336 ((vtmsgs vtmsgs) (reason (eql 'vtmsgs)) sequencer)
1f1d88f5 337 (when (vtmsgs-entries vtmsgs)
4b8e5c03 338 (with-slots ((class %class) subclass) vtmsgs
1f1d88f5
MW
339 (sequence-output (stream sequencer)
340 :constraint ((subclass :vtmsgs :start)
341 (subclass :vtmsgs class :start)
342 (subclass :vtmsgs class :slots)
343 (subclass :vtmsgs class :end)
344 (subclass :vtmsgs :end))
345 ((subclass :vtmsgs class :start)
a07d8d00 346 (format stream "/* Messages protocol from class ~A */~@
ddee4bb1
MW
347 struct ~A {~%"
348 class
349 (vtmsgs-struct-tag subclass class)))
1f1d88f5
MW
350 ((subclass :vtmsgs class :end)
351 (format stream "};~2%"))))))
352
1224dfb0
MW
353(defmethod hook-output progn
354 ((entry method-entry) (reason (eql 'vtmsgs)) sequencer)
ddee4bb1
MW
355 (let* ((method (method-entry-effective-method entry))
356 (message (effective-method-message method))
1f1d88f5 357 (class (effective-method-class method))
9ec578d9
MW
358 (function-type (method-entry-function-type entry))
359 (commented-type (commentify-function-type function-type))
360 (pointer-type (make-pointer-type commented-type)))
1f1d88f5
MW
361 (sequence-output (stream sequencer)
362 ((class :vtmsgs (sod-message-class message) :slots)
363 (pprint-logical-block (stream nil :prefix " " :suffix ";")
b426ab51 364 (pprint-c-type pointer-type stream (method-entry-slot-name entry)))
1f1d88f5
MW
365 (terpri stream)))))
366
1224dfb0
MW
367(defmethod hook-output progn
368 ((cptr class-pointer) (reason (eql :h)) sequencer)
4b8e5c03 369 (with-slots ((class %class) chain-head metaclass meta-chain-head) cptr
64fd357d
MW
370 (when (eq chain-head (sod-class-chain-head class))
371 (sequence-output (stream sequencer)
372 ((class :vtable chain-head :slots)
373 (format stream " const ~A *~:[_class~;~:*_cls_~A~];~%"
374 metaclass
375 (and (sod-class-direct-superclasses meta-chain-head)
376 (sod-class-nickname meta-chain-head))))))))
1f1d88f5 377
5b0a2bdb 378(defmethod hook-output progn ((boff base-offset) (reason (eql :h)) sequencer)
4b8e5c03 379 (with-slots ((class %class) chain-head) boff
64fd357d
MW
380 (when (eq chain-head (sod-class-chain-head class))
381 (sequence-output (stream sequencer)
382 ((class :vtable chain-head :slots)
383 (write-line " size_t _base;" stream))))))
1f1d88f5 384
1224dfb0
MW
385(defmethod hook-output progn
386 ((choff chain-offset) (reason (eql :h)) sequencer)
4b8e5c03 387 (with-slots ((class %class) chain-head target-head) choff
64fd357d
MW
388 (when (eq chain-head (sod-class-chain-head class))
389 (sequence-output (stream sequencer)
390 ((class :vtable chain-head :slots)
391 (format stream " ptrdiff_t _off_~A;~%"
392 (sod-class-nickname target-head)))))))
1f1d88f5 393
3be8c2bf
MW
394;;;--------------------------------------------------------------------------
395;;; Implementation output.
396
6e2d4b52 397(export '*instance-class*)
4b856491
MW
398(defvar *instance-class* nil
399 "The class currently being output.
400
401 This is bound during the `hook-output' traversal of a class layout for
402 `:c' output, since some of the objects traversed actually `belong' to
403 superclasses and there's no other way to find out what the reference class
404 actually is.
405
406 It may be bound at other times.")
3be8c2bf 407
5b0a2bdb 408(defmethod hook-output progn ((class sod-class) (reason (eql :c)) sequencer)
3be8c2bf
MW
409 (sequence-output (stream sequencer)
410
411 :constraint
412 ((:classes :start)
413 (class :banner)
414 (class :direct-methods :start) (class :direct-methods :end)
a07d8d00 415 (class :effective-methods)
3be8c2bf
MW
416 (class :vtables :start) (class :vtables :end)
417 (class :object :prepare) (class :object :start) (class :object :end)
418 (:classes :end))
419
420 ((class :banner)
421 (banner (format nil "Class ~A" class) stream))
422
423 ((class :object :start)
424 (format stream "~
425/* The class object. */
426const struct ~A ~A__classobj = {~%"
427 (ilayout-struct-tag (sod-class-metaclass class))
428 class))
429 ((class :object :end)
430 (format stream "};~2%")))
431
432 (let ((*instance-class* class))
dea4d055 433 (hook-output (sod-class-ilayout (sod-class-metaclass class))
6e2d4b52 434 'class sequencer)))
3be8c2bf
MW
435
436;;;--------------------------------------------------------------------------
9ec578d9 437;;; Direct and effective methods.
3be8c2bf 438
1224dfb0
MW
439(defmethod hook-output progn
440 ((method delegating-direct-method) (reason (eql :c)) sequencer)
4b8e5c03 441 (with-slots ((class %class) body) method
3be8c2bf 442 (unless body
dea4d055 443 (return-from hook-output))
3be8c2bf
MW
444 (sequence-output (stream sequencer)
445 ((class :direct-method method :start)
446 (format stream "#define CALL_NEXT_METHOD (next_method(~{~A~^, ~}))~%"
447 (mapcar #'argument-name
448 (c-function-arguments (sod-method-next-method-type
449 method)))))
450 ((class :direct-method method :end)
451 (format stream "#undef CALL_NEXT_METHOD~%")))))
452
1224dfb0
MW
453(defmethod hook-output progn
454 ((method sod-method) (reason (eql :c)) sequencer)
4b8e5c03 455 (with-slots ((class %class) body) method
3be8c2bf 456 (unless body
dea4d055 457 (return-from hook-output))
3be8c2bf
MW
458 (sequence-output (stream sequencer)
459 :constraint ((class :direct-methods :start)
460 (class :direct-method method :start)
461 (class :direct-method method :body)
462 (class :direct-method method :end)
463 (class :direct-methods :end))
464 ((class :direct-method method :body)
465 (pprint-c-type (sod-method-function-type method)
466 stream
467 (sod-method-function-name method))
468 (format stream "~&{~%")
469 (write body :stream stream :pretty nil :escape nil)
470 (format stream "~&}~%"))
471 ((class :direct-method method :end)
472 (terpri stream)))))
473
1224dfb0
MW
474(defmethod hook-output progn
475 ((method basic-effective-method) (reason (eql :c)) sequencer)
4b8e5c03 476 (with-slots ((class %class) functions) method
dea4d055
MW
477 (sequence-output (stream sequencer)
478 ((class :effective-methods)
479 (dolist (func functions)
480 (write func :stream stream :escape nil :circle nil))))))
481
a07d8d00
MW
482;;;--------------------------------------------------------------------------
483;;; Vtables.
484
5b0a2bdb 485(defmethod hook-output progn ((vtable vtable) (reason (eql :c)) sequencer)
4b8e5c03 486 (with-slots ((class %class) chain-head chain-tail) vtable
a07d8d00
MW
487 (sequence-output (stream sequencer)
488 :constraint ((class :vtables :start)
489 (class :vtable chain-head :start)
490 (class :vtable chain-head :end)
491 (class :vtables :end))
492 ((class :vtable chain-head :start)
493 (format stream "/* Vtable for ~A chain. */~@
c2438e62 494 const union ~A ~A = { {~%"
a07d8d00 495 chain-head
c2438e62 496 (vtable-union-tag chain-tail chain-head)
9ec578d9 497 (vtable-name class chain-head)))
a07d8d00 498 ((class :vtable chain-head :end)
c2438e62 499 (format stream "} };~2%")))))
a07d8d00 500
1224dfb0
MW
501(defmethod hook-output progn
502 ((cptr class-pointer) (reason (eql :c)) sequencer)
4b8e5c03 503 (with-slots ((class %class) chain-head metaclass meta-chain-head) cptr
a07d8d00
MW
504 (sequence-output (stream sequencer)
505 :constraint ((class :vtable chain-head :start)
506 (class :vtable chain-head :class-pointer metaclass)
507 (class :vtable chain-head :end))
508 ((class :vtable chain-head :class-pointer metaclass)
9ec578d9
MW
509 (format stream " /* ~21@A = */ &~A__classobj.~A.~A,~%"
510 (if (sod-class-direct-superclasses meta-chain-head)
511 (format nil "_cls_~A"
512 (sod-class-nickname meta-chain-head))
513 "_class")
fc5d9486 514 class
a07d8d00
MW
515 (sod-class-nickname meta-chain-head)
516 (sod-class-nickname metaclass))))))
517
5b0a2bdb 518(defmethod hook-output progn ((boff base-offset) (reason (eql :c)) sequencer)
4b8e5c03 519 (with-slots ((class %class) chain-head) boff
a07d8d00
MW
520 (sequence-output (stream sequencer)
521 :constraint ((class :vtable chain-head :start)
522 (class :vtable chain-head :base-offset)
523 (class :vtable chain-head :end))
524 ((class :vtable chain-head :base-offset)
9ec578d9
MW
525 (format stream " /* ~21@A = */ offsetof(struct ~A, ~A),~%"
526 "_base"
a07d8d00
MW
527 (ilayout-struct-tag class)
528 (sod-class-nickname chain-head))))))
529
1224dfb0
MW
530(defmethod hook-output progn
531 ((choff chain-offset) (reason (eql :c)) sequencer)
4b8e5c03 532 (with-slots ((class %class) chain-head target-head) choff
a07d8d00
MW
533 (sequence-output (stream sequencer)
534 :constraint ((class :vtable chain-head :start)
535 (class :vtable chain-head :chain-offset target-head)
536 (class :vtable chain-head :end))
537 ((class :vtable chain-head :chain-offset target-head)
9ec578d9
MW
538 (format stream " /* ~21@A = */ SOD_OFFSETDIFF(struct ~A, ~A, ~A),~%"
539 (format nil "_off_~A" (sod-class-nickname target-head))
a07d8d00
MW
540 (ilayout-struct-tag class)
541 (sod-class-nickname chain-head)
542 (sod-class-nickname target-head))))))
543
5b0a2bdb 544(defmethod hook-output progn ((vtmsgs vtmsgs) (reason (eql :c)) sequencer)
4b8e5c03 545 (with-slots ((class %class) subclass chain-head) vtmsgs
a07d8d00
MW
546 (sequence-output (stream sequencer)
547 :constraint ((subclass :vtable chain-head :start)
548 (subclass :vtable chain-head :vtmsgs class :start)
549 (subclass :vtable chain-head :vtmsgs class :slots)
550 (subclass :vtable chain-head :vtmsgs class :end)
551 (subclass :vtable chain-head :end))
552 ((subclass :vtable chain-head :vtmsgs class :start)
553 (format stream " { /* Method entries for ~A messages. */~%"
554 class))
555 ((subclass :vtable chain-head :vtmsgs class :end)
556 (format stream " },~%")))))
557
1224dfb0
MW
558(defmethod hook-output progn
559 ((entry method-entry) (reason (eql :c)) sequencer)
4b8e5c03 560 (with-slots ((method %method) chain-head chain-tail role) entry
a07d8d00
MW
561 (let* ((message (effective-method-message method))
562 (class (effective-method-class method))
563 (super (sod-message-class message)))
564 (sequence-output (stream sequencer)
565 ((class :vtable chain-head :vtmsgs super :slots)
9ec578d9 566 (format stream " /* ~19@A = */ ~A,~%"
b426ab51
MW
567 (method-entry-slot-name entry)
568 (method-entry-function-name method chain-head role)))))))
a07d8d00 569
3be8c2bf
MW
570;;;--------------------------------------------------------------------------
571;;; Filling in the class object.
572
1224dfb0
MW
573(defmethod hook-output progn
574 ((ichain ichain) (reason (eql 'class)) sequencer)
4b8e5c03 575 (with-slots ((class %class) chain-head) ichain
3be8c2bf
MW
576 (sequence-output (stream sequencer)
577 :constraint ((*instance-class* :object :start)
578 (*instance-class* :object chain-head :ichain :start)
579 (*instance-class* :object chain-head :ichain :end)
580 (*instance-class* :object :end))
581 ((*instance-class* :object chain-head :ichain :start)
582 (format stream " { { /* ~A ichain */~%"
583 (sod-class-nickname chain-head)))
584 ((*instance-class* :object chain-head :ichain :end)
585 (format stream " } },~%")))))
586
1224dfb0
MW
587(defmethod hook-output progn
588 ((islots islots) (reason (eql 'class)) sequencer)
4b8e5c03 589 (with-slots ((class %class)) islots
3be8c2bf
MW
590 (let ((chain-head (sod-class-chain-head class)))
591 (sequence-output (stream sequencer)
592 :constraint ((*instance-class* :object chain-head :ichain :start)
593 (*instance-class* :object class :slots :start)
594 (*instance-class* :object class :slots)
595 (*instance-class* :object class :slots :end)
596 (*instance-class* :object chain-head :ichain :end))
597 ((*instance-class* :object class :slots :start)
598 (format stream " { /* Class ~A */~%" class))
599 ((*instance-class* :object class :slots :end)
600 (format stream " },~%"))))))
601
1224dfb0
MW
602(defmethod hook-output progn
603 ((vtptr vtable-pointer) (reason (eql 'class)) sequencer)
4b8e5c03 604 (with-slots ((class %class) chain-head chain-tail) vtptr
3be8c2bf
MW
605 (sequence-output (stream sequencer)
606 :constraint ((*instance-class* :object chain-head :ichain :start)
607 (*instance-class* :object chain-head :vtable)
608 (*instance-class* :object chain-head :ichain :end))
609 ((*instance-class* :object chain-head :vtable)
c2438e62
MW
610 (format stream " /* ~17@A = */ &~A.~A,~%"
611 "_vt"
612 (vtable-name class chain-head)
613 (sod-class-nickname chain-tail))))))
3be8c2bf
MW
614
615(defgeneric find-class-initializer (slot class)
616 (:method ((slot effective-slot) (class sod-class))
617 (let ((dslot (effective-slot-direct-slot slot)))
618 (or (some (lambda (super)
619 (find dslot (sod-class-class-initializers super)
620 :test #'sod-initializer-slot))
621 (sod-class-precedence-list class))
622 (effective-slot-initializer slot)))))
623
624(defgeneric output-class-initializer (slot instance stream)
625 (:method ((slot sod-class-effective-slot) (instance sod-class) stream)
9ec578d9
MW
626 (let ((func (effective-slot-initializer-function slot))
627 (direct-slot (effective-slot-direct-slot slot)))
3be8c2bf 628 (if func
9ec578d9
MW
629 (format stream " /* ~15@A = */ ~A,~%"
630 (sod-slot-name direct-slot)
631 (funcall func instance))
3be8c2bf
MW
632 (call-next-method))))
633 (:method ((slot effective-slot) (instance sod-class) stream)
9ec578d9
MW
634 (let ((init (find-class-initializer slot instance))
635 (direct-slot (effective-slot-direct-slot slot)))
3be8c2bf 636 (ecase (sod-initializer-value-kind init)
9ec578d9
MW
637 (:simple (format stream " /* ~15@A = */ ~A,~%"
638 (sod-slot-name direct-slot)
3be8c2bf 639 (sod-initializer-value-form init)))
9ec578d9
MW
640 (:compound (format stream " /* ~15@A = */ ~@<{ ~;~A~; },~:>~%"
641 (sod-slot-name direct-slot)
642 (sod-initializer-value-form init)))))))
3be8c2bf 643
1224dfb0
MW
644(defmethod hook-output progn
645 ((slot sod-class-effective-slot) (reason (eql 'class)) sequencer)
3be8c2bf
MW
646 (let ((instance *instance-class*)
647 (func (effective-slot-prepare-function slot)))
648 (when func
649 (sequence-output (stream sequencer)
650 ((instance :object :prepare)
651 (funcall func instance stream))))))
652
1224dfb0
MW
653(defmethod hook-output progn
654 ((slot effective-slot) (reason (eql 'class)) sequencer)
4b8e5c03 655 (with-slots ((class %class) (dslot slot)) slot
3be8c2bf
MW
656 (let ((instance *instance-class*)
657 (super (sod-slot-class dslot)))
658 (sequence-output (stream sequencer)
659 ((instance :object super :slots)
660 (output-class-initializer slot instance stream))))))
661
1f1d88f5 662;;;----- That's all, folks --------------------------------------------------