glib: make arguments in type decision procedure ignorable to inhibit warnings
[cl-gtk2.git] / glib / gobject.boxed.lisp
index 0c7f8be..61eacee 100644 (file)
 
 (eval-when (:load-toplevel :compile-toplevel :execute)
   (defstruct (g-boxed-cstruct-wrapper-info (:include g-boxed-info))
-    cstruct
-    slots))
+    cstruct-description))
 
 (defclass boxed-cstruct-foreign-type (g-boxed-foreign-type) ())
 
+(defstruct cstruct-slot-description
+  name
+  type
+  count
+  initform)
+
+(defmethod make-load-form ((object cstruct-slot-description) &optional environment)
+  (make-load-form-saving-slots object :environment environment))
+
+(defstruct cstruct-description
+  name
+  slots)
+
+(defmethod make-load-form ((object cstruct-description) &optional environment)
+  (make-load-form-saving-slots object :environment environment))
+
+(defun parse-cstruct-slot (slot)
+  (destructuring-bind (name type &key count initform) slot
+    (make-cstruct-slot-description :name name :type type :count count :initform initform)))
+
+(defun parse-cstruct-definition (name slots)
+  (make-cstruct-description :name name
+                            :slots (mapcar #'parse-cstruct-slot slots)))
+
 (defmacro define-g-boxed-cstruct (name g-type-name &body slots)
-  `(progn
-     (defstruct ,name
-       ,@(iter (for (name type &key count initarg) in slots)
-               (collect (list name initarg))))
-     (defcstruct ,(generated-cstruct-name name)
-       ,@(iter (for (name type &key count initarg) in slots)
-               (collect `(,name ,type ,@(when count `(:count ,count))))))
-     (eval-when (:compile-toplevel :load-toplevel :execute)
-       (setf (get ',name 'g-boxed-foreign-info)
-             (make-g-boxed-cstruct-wrapper-info :name ',name
-                                                :g-type ,g-type-name
-                                                :cstruct ',(generated-cstruct-name name)
-                                                :slots ',(iter (for (name type &key initarg) in slots)
-                                                               (collect name)))
-             (gethash ,g-type-name *g-type-name->g-boxed-foreign-info*)
-             (get ',name 'g-boxed-foreign-info)))))
+  (let ((cstruct-description (parse-cstruct-definition name slots)))
+    `(progn
+       (defstruct ,name
+         ,@(iter (for slot in (cstruct-description-slots cstruct-description))
+                 (for name = (cstruct-slot-description-name slot))
+                 (for initform = (cstruct-slot-description-initform slot))
+                 (collect (list name initform))))
+       (defcstruct ,(generated-cstruct-name name)
+         ,@(iter (for slot in (cstruct-description-slots cstruct-description))
+                 (for name = (cstruct-slot-description-name slot))
+                 (for type = (cstruct-slot-description-type slot))
+                 (for count = (cstruct-slot-description-count slot))
+                 (collect `(,name ,type ,@(when count `(:count ,count))))))
+       (defcunion ,(generated-cunion-name name)
+         (,name ,(generated-cstruct-name name)))
+       (eval-when (:compile-toplevel :load-toplevel :execute)
+         (setf (get ',name 'g-boxed-foreign-info)
+               (make-g-boxed-cstruct-wrapper-info :name ',name
+                                                  :g-type ,g-type-name
+                                                  :cstruct-description ,cstruct-description)
+               (gethash ,g-type-name *g-type-name->g-boxed-foreign-info*)
+               (get ',name 'g-boxed-foreign-info))))))
 
 (defmethod make-foreign-type ((info g-boxed-cstruct-wrapper-info) &key return-p)
   (make-instance 'boxed-cstruct-foreign-type :info info :return-p return-p))
 (defmethod boxed-copy-fn ((info g-boxed-cstruct-wrapper-info) native)
   (if (g-boxed-info-g-type info)
       (g-boxed-copy (g-boxed-info-g-type info) native)
-      (let ((copy (foreign-alloc (g-boxed-cstruct-wrapper-info-cstruct info))))
-        (memcpy copy native (foreign-type-size (g-boxed-cstruct-wrapper-info-cstruct info)))
+      (let ((copy (foreign-alloc (generated-cstruct-name (g-boxed-info-name info)))))
+        (memcpy copy native (foreign-type-size (generated-cstruct-name (g-boxed-info-name info))))
         copy)))
 
 (defmethod boxed-free-fn ((info g-boxed-cstruct-wrapper-info) native)
       (g-boxed-free (g-boxed-info-g-type info) native)
       (foreign-free native)))
 
+(defun copy-slots-to-native (proxy native cstruct-description)
+  (iter (with cstruct-type = (generated-cstruct-name (cstruct-description-name cstruct-description)))
+        (for slot in (cstruct-description-slots cstruct-description))
+        (for slot-name = (cstruct-slot-description-name slot))
+        (cond
+          ((cstruct-slot-description-count slot)
+           (iter (with ptr = (foreign-slot-pointer native cstruct-type slot-name))
+                 (with array = (slot-value proxy slot-name))
+                 (for i from 0 below (cstruct-slot-description-count slot))
+                 (setf (mem-aref ptr (cstruct-slot-description-type slot) i)
+                       (aref array i))))
+          (t
+           (setf (foreign-slot-value native cstruct-type slot-name)
+                 (slot-value proxy slot-name))))))
+
+(defun copy-slots-to-proxy (proxy native cstruct-description)
+  (iter (with cstruct-type = (generated-cstruct-name (cstruct-description-name cstruct-description)))
+        (for slot in (cstruct-description-slots cstruct-description))
+        (for slot-name = (cstruct-slot-description-name slot))
+        (cond
+          ((cstruct-slot-description-count slot)
+           (setf (slot-value proxy slot-name) (make-array (list (cstruct-slot-description-count slot))))
+           (iter (with ptr = (foreign-slot-pointer native cstruct-type slot-name))
+                 (with array = (slot-value proxy slot-name))
+                 (for i from 0 below (cstruct-slot-description-count slot))
+                 (setf (aref array i)
+                       (mem-aref ptr (cstruct-slot-description-type slot) i))))
+          (t (setf (slot-value proxy slot-name)
+                   (foreign-slot-value native cstruct-type slot-name))))))
+
 (defmethod translate-to-foreign (proxy (type boxed-cstruct-foreign-type))
   (if (null proxy)
       (null-pointer)
       (let* ((info (g-boxed-foreign-info type))
-             (native-structure-type (g-boxed-cstruct-wrapper-info-cstruct info)))
+             (native-structure-type (generated-cstruct-name (g-boxed-info-name info))))
         (with-foreign-object (native-structure native-structure-type)
-          (iter (for slot in (g-boxed-cstruct-wrapper-info-slots info))
-                (setf (foreign-slot-value native-structure native-structure-type slot)
-                      (slot-value proxy slot)))
+          (copy-slots-to-native proxy native-structure (g-boxed-cstruct-wrapper-info-cstruct-description info))
           (values (boxed-copy-fn info native-structure) proxy)))))
 
 (defmethod free-translated-object (native-structure (type boxed-cstruct-foreign-type) proxy)
   (when proxy
-    (let* ((info (g-boxed-foreign-info type))
-           (native-structure-type (g-boxed-cstruct-wrapper-info-cstruct info)))
-      (iter (for slot in (g-boxed-cstruct-wrapper-info-slots info))
-            (setf (slot-value proxy slot)
-                  (foreign-slot-value native-structure native-structure-type slot)))
+    (let ((info (g-boxed-foreign-info type)))
+      (copy-slots-to-proxy proxy native-structure (g-boxed-cstruct-wrapper-info-cstruct-description info))
       (boxed-free-fn info native-structure))))
 
 (defmethod translate-from-foreign (native-structure (type boxed-cstruct-foreign-type))
   (unless (null-pointer-p native-structure)
     (let* ((info (g-boxed-foreign-info type))
-           (native-structure-type (g-boxed-cstruct-wrapper-info-cstruct info))
            (proxy-structure-type (g-boxed-info-name info))
            (proxy (make-instance proxy-structure-type)))
-      (iter (for slot in (g-boxed-cstruct-wrapper-info-slots info))
-            (setf (slot-value proxy slot)
-                  (foreign-slot-value native-structure native-structure-type slot)))
+      (copy-slots-to-proxy proxy native-structure (g-boxed-cstruct-wrapper-info-cstruct-description info))
       (when (g-boxed-foreign-return-p type)
         (boxed-free-fn info native-structure))
       proxy)))
 
 (defmethod cleanup-translated-object-for-callback ((type boxed-cstruct-foreign-type) proxy native-structure)
   (when proxy
-    (let* ((info (g-boxed-foreign-info type))
-           (native-structure-type (g-boxed-cstruct-wrapper-info-cstruct info)))
-      (iter (for slot in (g-boxed-cstruct-wrapper-info-slots info))
-            (setf (foreign-slot-value native-structure native-structure-type slot)
-                  (slot-value proxy slot))))))
+    (let ((info (g-boxed-foreign-info type)))
+      (copy-slots-to-native proxy native-structure (g-boxed-cstruct-wrapper-info-cstruct-description info)))))
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (defstruct (g-boxed-opaque-wrapper-info (:include g-boxed-info))
   parent
   slots
   discriminator-slot
-  variants)
+  variants
+  resulting-cstruct-description)
 
 (defstruct var-structure-variant
   discriminating-values
   structure)
 
-(defstruct var-structure-slot
-  name
-  type
-  initform
-  count)
-
 (defmethod make-load-form ((object var-structure) &optional env)
   (make-load-form-saving-slots object :environment env))
 
-(defmethod make-load-form ((object var-structure-slot) &optional env)
-  (make-load-form-saving-slots object :environment env))
-
 (defmethod make-load-form ((object var-structure-variant) &optional env)
   (make-load-form-saving-slots object :environment env))
 
                 (error "Structure has more than one discriminator slot"))
               (setf (var-structure-discriminator-slot result) (second slot)
                     (var-structure-variants result) (parse-variants result (nthcdr 2 slot))))
-            (push (parse-slot slot) (var-structure-slots result)))
+            (push (parse-cstruct-slot slot) (var-structure-slots result)))
         (finally (setf (var-structure-slots result)
                        (reverse (var-structure-slots result)))
+                 (unless parent
+                   (set-variant-result-structure result))
                  (return result))))
 
-(defun parse-slot (slot)
-  (destructuring-bind (name type &key count initform) slot
-    (make-var-structure-slot :name name :type type :count count :initform initform)))
+(defun set-variant-result-structure (var-structure)
+  (setf (var-structure-resulting-cstruct-description var-structure)
+        (make-cstruct-description
+         :name
+         (var-structure-name var-structure)
+         :slots
+         (append
+          (when (var-structure-parent var-structure)
+            (cstruct-description-slots (var-structure-resulting-cstruct-description (var-structure-parent var-structure))))
+          (var-structure-slots var-structure))))
+  (iter (for variant in (var-structure-variants var-structure))
+        (for child-var-structure = (var-structure-variant-structure variant))
+        (set-variant-result-structure child-var-structure)))
 
 (defun ensure-list (thing)
   (if (listp thing)
               :structure (parse-variant-structure-definition variant-name slots parent)))
         (collect variant)))
 
+(defpackage :gobject.boxed.generated-names)
+
 (defun generated-cstruct-name (symbol)
   (or (get symbol 'generated-cstruct-name)
-      (setf (get symbol 'generated-cstruct-name) (gensym (format nil "GEN-~A-CSTRUCT-" (symbol-name symbol))))))
+      (setf (get symbol 'generated-cstruct-name) (gentemp (format nil "CSTRUCT-~A" (symbol-name symbol)) (find-package :gobject.boxed.generated-names)))))
 
 (defun generated-cunion-name (symbol)
   (or (get symbol 'generated-cunion-name)
-      (setf (get symbol 'generated-cunion-name) (gensym (format nil "GEN-~A-CUNION-" (symbol-name symbol))))))
+      (setf (get symbol 'generated-cunion-name) (gentemp (format nil "CUNION-~A" (symbol-name symbol)) (find-package :gobject.boxed.generated-names)))))
 
 (defun generate-cstruct-1 (struct)
-  `(defcstruct ,(generated-cstruct-name (var-structure-name struct))
-     ,@(iter (for slot in (var-struct-all-slots struct))
-             (collect `(,(var-structure-slot-name slot) ,(var-structure-slot-type slot)
-                         ,@(when (var-structure-slot-count slot)
-                                 `(:count ,(var-structure-slot-count slot))))))))
+  `(defcstruct ,(generated-cstruct-name (cstruct-description-name struct))
+     ,@(iter (for slot in (cstruct-description-slots struct))
+             (collect `(,(cstruct-slot-description-name slot) ,(cstruct-slot-description-type slot)
+                         ,@(when (cstruct-slot-description-count slot)
+                                 `(:count ,(cstruct-slot-description-count slot))))))))
 
 (defun generate-c-structures (structure)
   (iter (for str in (all-structures structure))
-        (collect (generate-cstruct-1 str))))
+        (for cstruct = (var-structure-resulting-cstruct-description str))
+        (collect (generate-cstruct-1 cstruct))))
 
-(defun generate-union-1 (struct)
+(defun generate-variant-union (struct)
   `(defcunion ,(generated-cunion-name (var-structure-name struct))
-     ,@(iter (for variant in (all-structures struct))
-             (unless (eq struct variant)
-               (collect `(,(var-structure-name variant)
-                           ,(generated-cunion-name (var-structure-name variant))))))))
-
-(defun generate-unions (struct)
-  (iter (for str in (all-structures struct))
-        (collect (generate-union-1 str))))
+     ,@(iter (for str in (all-structures struct))
+             (collect `(,(var-structure-name str)
+                         ,(generated-cstruct-name (var-structure-name str)))))))
 
 (defun generate-structure-1 (str)
   `(defstruct ,(if (var-structure-parent str)
                                                                           :key #'var-structure-variant-structure))))))
                    `,(var-structure-name str))
      ,@(iter (for slot in (var-structure-slots str))
-             (collect `(,(var-structure-slot-name slot)
-                         ,(var-structure-slot-initform slot))))))
+             (collect `(,(cstruct-slot-description-name slot)
+                         ,(cstruct-slot-description-initform slot))))))
 
 (defun generate-structures (str)
   (iter (for variant in (reverse (all-structures str)))
 
 (defun generate-native-type-decision-procedure-1 (str proxy-var)
   (if (null (var-structure-discriminator-slot str))
-      `(values ',(generated-cstruct-name (var-structure-name str))
-               ',(mapcar #'var-structure-slot-name (var-struct-all-slots str)))
+      `(values ',(var-structure-resulting-cstruct-description str))
       `(typecase ,proxy-var
          ,@(iter (for variant in (var-structure-variants str))
                  (for v-str = (var-structure-variant-structure variant))
                  (collect `(,(var-structure-name v-str)
                              ,(generate-native-type-decision-procedure-1 v-str proxy-var))))
          (,(var-structure-name str)
-          (values ',(generated-cstruct-name (var-structure-name str))
-                  ',(mapcar #'var-structure-slot-name (var-struct-all-slots str)))))))
+          (values ',(var-structure-resulting-cstruct-description str))))))
 
 (defun generate-proxy-type-decision-procedure-1 (str native-var)
   (if (null (var-structure-discriminator-slot str))
       `(values ',(var-structure-name str)
-               ',(mapcar #'var-structure-slot-name (var-struct-all-slots str))
-               ',(generated-cstruct-name (var-structure-name str)))
+               ',(var-structure-resulting-cstruct-description str))
       `(case (foreign-slot-value ,native-var
                                  ',(generated-cstruct-name (var-structure-name str))
                                  ',(var-structure-discriminator-slot str))
                                v-str
                                native-var))))
          (t (values ',(var-structure-name str)
-                    ',(mapcar #'var-structure-slot-name (var-struct-all-slots str))
-                    ',(generated-cstruct-name (var-structure-name str)))))))
+                    ',(var-structure-resulting-cstruct-description str))))))
 
 (defun generate-proxy-type-decision-procedure (str)
   (let ((native (gensym "NATIVE-")))
     `(lambda (,native)
+       (declare (ignorable ,native))
        ,(generate-proxy-type-decision-procedure-1 str native))))
 
 (defun generate-native-type-decision-procedure (str)
   (let ((proxy (gensym "PROXY-")))
     `(lambda (,proxy)
+       (declare (ignorable ,proxy))
        ,(generate-native-type-decision-procedure-1 str proxy))))
 
 (defun compile-proxy-type-decision-procedure (str)
 (defmethod make-load-form ((object g-boxed-variant-cstruct-info) &optional env)
   (make-load-form-saving-slots object :environment env))
 
-(define-foreign-type boxed-variant-cstruct-foreign-type () ())
+(define-foreign-type boxed-variant-cstruct-foreign-type (g-boxed-foreign-type) ())
 
 (defmethod make-foreign-type ((info g-boxed-variant-cstruct-info) &key return-p)
   (make-instance 'boxed-variant-cstruct-foreign-type :info info :return-p return-p))
 (defmacro define-g-boxed-variant-cstruct (name g-type-name &body slots)
   (let* ((structure (parse-variant-structure-definition name slots)))
     `(progn ,@(generate-c-structures structure)
-            ,@(generate-unions structure)
+            ,(generate-variant-union structure)
             ,@(generate-structures structure)
             (eval-when (:compile-toplevel :load-toplevel :execute)
               (setf (get ',name 'g-boxed-foreign-info)
 (defmethod boxed-copy-fn ((info g-boxed-variant-cstruct-info) native)
   (if (g-boxed-info-g-type info)
       (g-boxed-copy (g-boxed-info-g-type info) native)
-      (let ((copy (foreign-alloc (generated-cstruct-name (g-boxed-info-name info)))))
-        (memcpy copy native (foreign-type-size (generated-cstruct-name (g-boxed-info-name info))))
+      (let ((copy (foreign-alloc (generated-cunion-name (g-boxed-info-name info)))))
+        (memcpy copy native (foreign-type-size (generated-cunion-name (g-boxed-info-name info))))
         copy)))
 
 (defmethod boxed-free-fn ((info g-boxed-variant-cstruct-info) native)
 (defmethod translate-to-foreign (proxy (foreign-type boxed-variant-cstruct-foreign-type))
   (if (null proxy)
       (null-pointer)
-      (let ((type (g-boxed-foreign-info foreign-type)))
-        (multiple-value-bind (actual-cstruct slots) (decide-native-type type proxy)
-          (with-foreign-object (native-structure (generated-cstruct-name
-                                                  (var-structure-name
-                                                   (g-boxed-variant-cstruct-info-root type))))
-            (iter (for slot in slots)
-                  (setf (foreign-slot-value native-structure actual-cstruct slot)
-                        (slot-value proxy slot)))
-            (values (boxed-copy-fn type native-structure) proxy))))))
+      (let* ((type (g-boxed-foreign-info foreign-type))
+             (cstruct-description (decide-native-type type proxy)))
+        (with-foreign-object (native-structure (generated-cstruct-name
+                                                (var-structure-name
+                                                 (g-boxed-variant-cstruct-info-root type))))
+          (copy-slots-to-native proxy native-structure cstruct-description)
+          (values (boxed-copy-fn type native-structure) proxy)))))
 
 (defun decide-proxy-type (info native-structure)
   (funcall (g-boxed-variant-cstruct-info-proxy-type-decision-procedure info) native-structure))
 (defmethod free-translated-object (native (foreign-type boxed-variant-cstruct-foreign-type) proxy)
   (when proxy
     (let ((type (g-boxed-foreign-info foreign-type)))
-      (multiple-value-bind (actual-struct slots actual-cstruct) (decide-proxy-type type native)
+      (multiple-value-bind (actual-struct cstruct-description) (decide-proxy-type type native)
         (unless (eq (type-of proxy) actual-struct)
           (restart-case
               (error "Expected type of boxed variant structure ~A and actual type ~A do not match"
                      (type-of proxy) actual-struct)
             (skip-parsing-values () (return-from free-translated-object))))
-        (iter (for slot in slots)
-              (setf (slot-value proxy slot)
-                    (foreign-slot-value native actual-cstruct slot)))))))
+        (copy-slots-to-proxy proxy native cstruct-description)
+        (boxed-free-fn type native)))))
 
-(defmethod translate-from-foreign (native (foreign-type g-boxed-variant-cstruct-info))
+(defmethod translate-from-foreign (native (foreign-type boxed-variant-cstruct-foreign-type))
   (unless (null-pointer-p native)
     (let ((type (g-boxed-foreign-info foreign-type)))
-      (multiple-value-bind (actual-struct slots actual-cstruct) (decide-proxy-type type native)
+      (multiple-value-bind (actual-struct cstruct-description) (decide-proxy-type type native)
         (let ((proxy (make-instance actual-struct)))
-          (iter (for slot in slots)
-                (setf (slot-value proxy slot)
-                      (foreign-slot-value native actual-cstruct slot)))
+          (copy-slots-to-proxy proxy native cstruct-description)
+          (when (g-boxed-foreign-return-p foreign-type)
+            (boxed-free-fn type native))
           proxy)))))
 
-(defmethod cleanup-translated-object-for-callback ((foreign-type g-boxed-variant-cstruct-info) proxy native)
+(defmethod cleanup-translated-object-for-callback ((foreign-type boxed-variant-cstruct-foreign-type) proxy native)
   (when proxy
     (let ((type (g-boxed-foreign-info foreign-type)))
-      (multiple-value-bind (actual-cstruct slots) (decide-native-type type proxy)
-        (iter (for slot in slots)
-              (setf (foreign-slot-value native actual-cstruct slot)
-                    (slot-value proxy slot)))))))
+      (let ((cstruct-description (decide-native-type type proxy)))
+        (copy-slots-to-native proxy native cstruct-description)))))
 
 (defgeneric boxed-parse-g-value (gvalue-ptr info))