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