src/method-impl.lisp (compute-method-entry-functions): Fix varargs handling.
[sod] / src / class-output.lisp
index 91dc0bf..a975ebe 100644 (file)
@@ -7,7 +7,7 @@
 
 ;;;----- Licensing notice ---------------------------------------------------
 ;;;
-;;; This file is part of the Sensble Object Design, an object system for C.
+;;; This file is part of the Sensible Object Design, an object system for C.
 ;;;
 ;;; SOD is free software; you can redistribute it and/or modify
 ;;; it under the terms of the GNU General Public License as published by
 (cl:in-package #:sod)
 
 ;;;--------------------------------------------------------------------------
+;;; Walking the layout tree.
+
+(defmethod hook-output progn ((class sod-class) reason sequencer)
+  (with-slots ((ilayout %ilayout) vtables methods effective-methods) class
+    (hook-output ilayout reason sequencer)
+    (dolist (method methods) (hook-output method reason sequencer))
+    (dolist (method effective-methods) (hook-output method reason sequencer))
+    (dolist (vtable vtables) (hook-output vtable reason sequencer))))
+
+(defmethod hook-output progn ((ilayout ilayout) reason sequencer)
+  (with-slots (ichains) ilayout
+    (dolist (ichain ichains) (hook-output ichain reason sequencer))))
+
+(defmethod hook-output progn ((ichain ichain) reason sequencer)
+  (dolist (item (ichain-body ichain)) (hook-output item reason sequencer)))
+
+(defmethod hook-output progn ((islots islots) reason sequencer)
+  (dolist (slot (islots-slots islots)) (hook-output slot reason sequencer)))
+
+(defmethod hook-output progn ((vtable vtable) reason sequencer)
+  (with-slots (body) vtable
+    (dolist (item body) (hook-output item reason sequencer))))
+
+(defmethod hook-output progn ((vtmsgs vtmsgs) reason sequencer)
+  (with-slots (entries) vtmsgs
+    (dolist (entry entries) (hook-output entry reason sequencer))))
+
+;;;--------------------------------------------------------------------------
 ;;; Classes.
 
 (defmethod hook-output progn ((class sod-class) (reason (eql :h)) sequencer)
                                raw-name)))
                 (cond ((and (cdr args) (eq (cadr args) :ellipsis))
                        (setf varargsp t)
-                       (unless in-names (setf me "SOD_CAR(__VA_ARGS__)"))
+                       (unless in-names (setf me "SOD__CAR(__VA_ARGS__)"))
                        (push (format nil "/*~A*/ ..." name) in-names)
                        (push "__VA_ARGS__" out-names)
                        (return))
         (terpri stream)))))
 
   ;; Generate vtmsgs structure for all superclasses.
-  (hook-output (car (sod-class-vtables class))
-                   'vtmsgs
-                   sequencer))
-
-(defmethod hook-output progn ((class sod-class) reason sequencer)
-  (with-slots ((ilayout %ilayout) vtables methods effective-methods) class
-    (hook-output ilayout reason sequencer)
-    (dolist (method methods) (hook-output method reason sequencer))
-    (dolist (method effective-methods) (hook-output method reason sequencer))
-    (dolist (vtable vtables) (hook-output vtable reason sequencer))))
+  (hook-output (car (sod-class-vtables class)) 'vtmsgs sequencer))
 
 ;;;--------------------------------------------------------------------------
 ;;; Instance structure.
 
-(defmethod hook-output progn ((slot sod-slot)
-                             (reason (eql 'islots))
-                             sequencer)
+(defmethod hook-output progn
+    ((slot sod-slot) (reason (eql 'islots)) sequencer)
   (sequence-output (stream sequencer)
     (((sod-slot-class slot) :islots :slots)
      (pprint-logical-block (stream nil :prefix "  " :suffix ";")
        (pprint-c-type (sod-slot-type slot) stream (sod-slot-name slot)))
      (terpri stream))))
 
-(defmethod hook-output progn ((ilayout ilayout) reason sequencer)
-  (with-slots (ichains) ilayout
-    (dolist (ichain ichains) (hook-output ichain reason sequencer))))
-
-(defmethod hook-output progn ((ichain ichain) reason sequencer)
-  (dolist (item (ichain-body ichain))
-    (hook-output item reason sequencer)))
-
 (defmethod hook-output progn ((ilayout ilayout) (reason (eql :h)) sequencer)
   (with-slots ((class %class) ichains) ilayout
     (sequence-output (stream sequencer)
                                 (sod-class-nickname super)))
                         (sod-class-chain chain-tail))))))))
 
-(defmethod hook-output progn ((ichain ichain)
-                             (reason (eql 'ilayout))
-                             sequencer)
+(defmethod hook-output progn
+    ((ichain ichain) (reason (eql 'ilayout)) sequencer)
   (with-slots ((class %class) chain-head chain-tail) ichain
     (sequence-output (stream sequencer)
       ((class :ilayout :slots)
        (format stream "  const struct ~A *_vt;~%"
               (vtable-struct-tag chain-tail chain-head))))))
 
-(defmethod hook-output progn ((islots islots) reason sequencer)
-  (dolist (slot (islots-slots islots))
-    (hook-output slot reason sequencer)))
-
 (defmethod hook-output progn ((islots islots) (reason (eql :h)) sequencer)
   (with-slots ((class %class) subclass slots) islots
     (sequence-output (stream sequencer)
 ;;;--------------------------------------------------------------------------
 ;;; Vtable structure.
 
-(defmethod hook-output progn ((vtable vtable) reason sequencer)
-  (with-slots (body) vtable
-    (dolist (item body) (hook-output item reason sequencer))))
-
-(defmethod hook-output progn ((method sod-method)
-                             (reason (eql :h))
-                             sequencer)
+(defmethod hook-output progn
+    ((method sod-method) (reason (eql :h)) sequencer)
   (with-slots ((class %class)) method
     (sequence-output (stream sequencer)
       ((class :methods)
               (vtmsgs-struct-tag subclass class)
               (sod-class-nickname class))))))
 
-(defmethod hook-output progn ((vtmsgs vtmsgs)
-                             (reason (eql 'vtmsgs))
-                             sequencer)
+(defmethod hook-output progn
+    ((vtmsgs vtmsgs) (reason (eql 'vtmsgs)) sequencer)
   (when (vtmsgs-entries vtmsgs)
     (with-slots ((class %class) subclass) vtmsgs
       (sequence-output (stream sequencer)
        ((subclass :vtmsgs class :end)
         (format stream "};~2%"))))))
 
-(defmethod hook-output progn ((vtmsgs vtmsgs) reason sequencer)
-  (with-slots (entries) vtmsgs
-    (dolist (entry entries) (hook-output entry reason sequencer))))
-
-(defmethod hook-output progn ((entry method-entry)
-                             (reason (eql 'vtmsgs))
-                             sequencer)
+(defmethod hook-output progn
+    ((entry method-entry) (reason (eql 'vtmsgs)) sequencer)
   (let* ((method (method-entry-effective-method entry))
         (message (effective-method-message method))
         (class (effective-method-class method))
         (pprint-c-type pointer-type stream (method-entry-slot-name entry)))
        (terpri stream)))))
 
-(defmethod hook-output progn ((cptr class-pointer)
-                             (reason (eql :h))
-                             sequencer)
+(defmethod hook-output progn
+    ((cptr class-pointer) (reason (eql :h)) sequencer)
   (with-slots ((class %class) chain-head metaclass meta-chain-head) cptr
     (sequence-output (stream sequencer)
       ((class :vtable chain-head :slots)
       ((class :vtable chain-head :slots)
        (write-line "  size_t _base;" stream)))))
 
-(defmethod hook-output progn ((choff chain-offset)
-                             (reason (eql :h))
-                             sequencer)
+(defmethod hook-output progn
+    ((choff chain-offset) (reason (eql :h)) sequencer)
   (with-slots ((class %class) chain-head target-head) choff
     (sequence-output (stream sequencer)
       ((class :vtable chain-head :slots)
 ;;;--------------------------------------------------------------------------
 ;;; Implementation output.
 
-(defvar *instance-class*)
+(export '*instance-class*)
+(defvar *instance-class* nil
+  "The class currently being output.
+
+   This is bound during the `hook-output' traversal of a class layout for
+   `:c' output, since some of the objects traversed actually `belong' to
+   superclasses and there's no other way to find out what the reference class
+   actually is.
+
+   It may be bound at other times.")
 
 (defmethod hook-output progn ((class sod-class) (reason (eql :c)) sequencer)
   (sequence-output (stream sequencer)
@@ -418,15 +419,13 @@ const struct ~A ~A__classobj = {~%"
 
   (let ((*instance-class* class))
     (hook-output (sod-class-ilayout (sod-class-metaclass class))
-                     'class
-                     sequencer)))
+                'class sequencer)))
 
 ;;;--------------------------------------------------------------------------
 ;;; Direct and effective methods.
 
-(defmethod hook-output progn ((method delegating-direct-method)
-                             (reason (eql :c))
-                             sequencer)
+(defmethod hook-output progn
+    ((method delegating-direct-method) (reason (eql :c)) sequencer)
   (with-slots ((class %class) body) method
     (unless body
       (return-from hook-output))
@@ -439,9 +438,8 @@ const struct ~A ~A__classobj = {~%"
       ((class :direct-method method :end)
        (format stream "#undef CALL_NEXT_METHOD~%")))))
 
-(defmethod hook-output progn ((method sod-method)
-                             (reason (eql :c))
-                             sequencer)
+(defmethod hook-output progn
+    ((method sod-method) (reason (eql :c)) sequencer)
   (with-slots ((class %class) body) method
     (unless body
       (return-from hook-output))
@@ -461,9 +459,8 @@ const struct ~A ~A__classobj = {~%"
       ((class :direct-method method :end)
        (terpri stream)))))
 
-(defmethod hook-output progn ((method basic-effective-method)
-                             (reason (eql :c))
-                             sequencer)
+(defmethod hook-output progn
+    ((method basic-effective-method) (reason (eql :c)) sequencer)
   (with-slots ((class %class) functions) method
     (sequence-output (stream sequencer)
       ((class :effective-methods)
@@ -489,9 +486,8 @@ const struct ~A ~A__classobj = {~%"
       ((class :vtable chain-head :end)
        (format stream "} };~2%")))))
 
-(defmethod hook-output progn ((cptr class-pointer)
-                             (reason (eql :c))
-                             sequencer)
+(defmethod hook-output progn
+    ((cptr class-pointer) (reason (eql :c)) sequencer)
   (with-slots ((class %class) chain-head metaclass meta-chain-head) cptr
     (sequence-output (stream sequencer)
       :constraint ((class :vtable chain-head :start)
@@ -519,9 +515,8 @@ const struct ~A ~A__classobj = {~%"
               (ilayout-struct-tag class)
               (sod-class-nickname chain-head))))))
 
-(defmethod hook-output progn ((choff chain-offset)
-                             (reason (eql :c))
-                             sequencer)
+(defmethod hook-output progn
+    ((choff chain-offset) (reason (eql :c)) sequencer)
   (with-slots ((class %class) chain-head target-head) choff
     (sequence-output (stream sequencer)
       :constraint ((class :vtable chain-head :start)
@@ -548,9 +543,8 @@ const struct ~A ~A__classobj = {~%"
       ((subclass :vtable chain-head :vtmsgs class :end)
        (format stream "  },~%")))))
 
-(defmethod hook-output progn ((entry method-entry)
-                             (reason (eql :c))
-                             sequencer)
+(defmethod hook-output progn
+    ((entry method-entry) (reason (eql :c)) sequencer)
   (with-slots ((method %method) chain-head chain-tail role) entry
     (let* ((message (effective-method-message method))
           (class (effective-method-class method))
@@ -564,9 +558,8 @@ const struct ~A ~A__classobj = {~%"
 ;;;--------------------------------------------------------------------------
 ;;; Filling in the class object.
 
-(defmethod hook-output progn ((ichain ichain)
-                             (reason (eql 'class))
-                             sequencer)
+(defmethod hook-output progn
+    ((ichain ichain) (reason (eql 'class)) sequencer)
   (with-slots ((class %class) chain-head) ichain
     (sequence-output (stream sequencer)
       :constraint ((*instance-class* :object :start)
@@ -579,9 +572,8 @@ const struct ~A ~A__classobj = {~%"
       ((*instance-class* :object chain-head :ichain :end)
        (format stream "  } },~%")))))
 
-(defmethod hook-output progn ((islots islots)
-                             (reason (eql 'class))
-                             sequencer)
+(defmethod hook-output progn
+    ((islots islots) (reason (eql 'class)) sequencer)
   (with-slots ((class %class)) islots
     (let ((chain-head (sod-class-chain-head class)))
       (sequence-output (stream sequencer)
@@ -595,9 +587,8 @@ const struct ~A ~A__classobj = {~%"
        ((*instance-class* :object class :slots :end)
         (format stream "      },~%"))))))
 
-(defmethod hook-output progn ((vtptr vtable-pointer)
-                             (reason (eql 'class))
-                             sequencer)
+(defmethod hook-output progn
+    ((vtptr vtable-pointer) (reason (eql 'class)) sequencer)
   (with-slots ((class %class) chain-head chain-tail) vtptr
     (sequence-output (stream sequencer)
       :constraint ((*instance-class* :object chain-head :ichain :start)
@@ -638,9 +629,8 @@ const struct ~A ~A__classobj = {~%"
                           (sod-slot-name direct-slot)
                           (sod-initializer-value-form init)))))))
 
-(defmethod hook-output progn ((slot sod-class-effective-slot)
-                             (reason (eql 'class))
-                             sequencer)
+(defmethod hook-output progn
+    ((slot sod-class-effective-slot) (reason (eql 'class)) sequencer)
   (let ((instance *instance-class*)
        (func (effective-slot-prepare-function slot)))
     (when func
@@ -648,9 +638,8 @@ const struct ~A ~A__classobj = {~%"
        ((instance :object :prepare)
         (funcall func instance stream))))))
 
-(defmethod hook-output progn ((slot effective-slot)
-                             (reason (eql 'class))
-                             sequencer)
+(defmethod hook-output progn
+    ((slot effective-slot) (reason (eql 'class)) sequencer)
   (with-slots ((class %class) (dslot slot)) slot
     (let ((instance *instance-class*)
          (super (sod-slot-class dslot)))