chiark / gitweb /
Added GET-ALL and PLIST-REMOVE to manipulate plists
[clg] / glib / gforeign.lisp
1 ;; Common Lisp bindings for GTK+ v2.0
2 ;; Copyright (C) 1999-2001 Espen S. Johnsen <esj@stud.cs.uit.no>
3 ;;
4 ;; This library is free software; you can redistribute it and/or
5 ;; modify it under the terms of the GNU Lesser General Public
6 ;; License as published by the Free Software Foundation; either
7 ;; version 2 of the License, or (at your option) any later version.
8 ;;
9 ;; This library is distributed in the hope that it will be useful,
10 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 ;; Lesser General Public License for more details.
13 ;;
14 ;; You should have received a copy of the GNU Lesser General Public
15 ;; License along with this library; if not, write to the Free Software
16 ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18 ;; $Id: gforeign.lisp,v 1.11 2001-10-21 16:50:43 espen Exp $
19
20 (in-package "GLIB")
21
22 ;;;; Type methods
23
24 (defvar *type-methods* (make-hash-table))
25
26 (defun ensure-type-method-fun (fname)
27   (unless (fboundp fname)
28     (setf
29      (symbol-function fname)
30      #'(lambda (type-spec &rest args)
31          (apply
32           (find-applicable-type-method type-spec fname) type-spec args)))))
33
34 (defmacro define-type-method-fun (fname lambda-list)
35   (declare (ignore lambda-list))
36   `(defun ,fname (type-spec &rest args)
37      (apply
38       (find-applicable-type-method type-spec ',fname) type-spec args)))
39
40
41 (defun ensure-type-name (type)
42   (etypecase type
43     (symbol type)
44     (pcl::class (class-name type))))
45
46 (defun add-type-method (type fname function)
47   (push
48    (cons fname function)
49    (gethash (ensure-type-name type) *type-methods*)))
50
51 (defun find-type-method (type fname)
52   (cdr (assoc fname (gethash (ensure-type-name type) *type-methods*))))
53
54 (defun find-applicable-type-method (type-spec fname &optional (error t))
55   (flet ((find-superclass-method (class)
56            (when (and class (class-finalized-p class))
57 ;            (unless (class-finalized-p class)
58 ;              (finalize-inheritance class))
59              (dolist (super (cdr (pcl::class-precedence-list class)))
60                (return-if (find-type-method super fname)))))
61          (find-expanded-type-method (type-spec)
62            (multiple-value-bind (expanded-type-spec expanded-p)
63                (type-expand-1 type-spec)
64              (cond
65               (expanded-p 
66                (find-applicable-type-method expanded-type-spec fname nil))
67               ((neq type-spec t)
68                (find-applicable-type-method t fname nil))))))
69
70     (or
71      (typecase type-spec
72        (pcl::class
73         (or
74          (find-type-method type-spec fname)
75          (find-superclass-method type-spec)))
76        (symbol
77         (or
78          (find-type-method type-spec fname)
79          (find-expanded-type-method type-spec)
80          (find-superclass-method (find-class type-spec nil))))
81        (cons
82         (or
83          (find-type-method (first type-spec) fname)
84          (find-expanded-type-method type-spec)))
85        (t
86         (error "Invalid type specifier ~A" type-spec)))
87      (and
88       error
89       (error
90        "No applicable method for ~A when called with type specifier ~A"
91        fname type-spec)))))
92
93 (defmacro deftype-method (fname type lambda-list &body body)
94   `(progn
95      (ensure-type-method-fun ',fname)
96      (add-type-method ',type ',fname #'(lambda ,lambda-list ,@body))
97      ',fname))
98   
99 ;; To make the compiler happy
100 (eval-when (:compile-toplevel :load-toplevel :execute)
101   (define-type-method-fun translate-type-spec (type-spec))
102   (define-type-method-fun size-of (type-spec))
103   (define-type-method-fun translate-to-alien (type-spec expr &optional weak-ref))
104   (define-type-method-fun translate-from-alien (type-spec expr &optional weak-ref))
105   (define-type-method-fun cleanup-alien (type-spec sap &otional weak-ref))
106   (define-type-method-fun unreference-alien (type-spec sap)))
107
108
109 ;;;; 
110
111 (defvar *type-function-cache* (make-hash-table :test #'equal))
112
113 (defun get-cached-function (type-spec fname)
114   (cdr (assoc fname (gethash type-spec *type-function-cache*))))
115
116 (defun set-cached-function (type-spec fname function)
117   (push (cons fname function) (gethash type-spec *type-function-cache*))
118   function)
119   
120
121 (defun intern-argument-translator (type-spec)
122   (or
123    (get-cached-function type-spec 'argument-translator)
124    (set-cached-function type-spec 'argument-translator
125     (compile
126      nil
127      `(lambda (object)
128         (declare (ignorable object))
129         ,(translate-to-alien type-spec 'object t))))))
130
131 (defun intern-return-value-translator (type-spec)
132   (or
133    (get-cached-function type-spec 'return-value-translator)
134    (set-cached-function type-spec 'return-value-translator
135     (compile
136      nil
137      `(lambda (alien)
138         (declare (ignorable alien))
139         ,(translate-from-alien type-spec 'alien nil))))))
140
141 (defun intern-cleanup-function (type-spec)
142   (or
143    (get-cached-function type-spec 'cleanup-function)
144    (set-cached-function type-spec 'cleanup-function
145     (compile
146      nil
147      `(lambda (alien)
148         (declare (ignorable alien))
149         ,(cleanup-alien type-spec 'alien t))))))
150
151
152
153 ;; Returns a function to write an object of the specified type
154 ;; to a memory location
155 (defun intern-writer-function (type-spec)
156   (or
157    (get-cached-function type-spec 'writer-function)
158    (set-cached-function type-spec 'writer-function
159     (compile
160      nil
161      `(lambda (value sap offset)
162         (declare (ignorable value sap offset))
163         (setf
164          (,(sap-ref-fname type-spec) sap offset)
165          ,(translate-to-alien type-spec 'value nil)))))))
166
167 ;; Returns a function to read an object of the specified type
168 ;; from a memory location
169 (defun intern-reader-function (type-spec)
170   (or
171    (get-cached-function type-spec 'reader-function)
172    (set-cached-function type-spec 'reader-function
173     (compile
174      nil
175      `(lambda (sap offset)       
176         (declare (ignorable sap offset))
177         ,(translate-from-alien
178           type-spec `(,(sap-ref-fname type-spec) sap offset) t))))))
179
180 (defun intern-destroy-function (type-spec)
181   (if (atomic-type-p type-spec)
182       #'(lambda (sap offset)     
183           (declare (ignore sap offset)))
184     (or
185      (get-cached-function type-spec 'destroy-function)
186      (set-cached-function type-spec 'destroy-function
187        (compile
188         nil
189         `(lambda (sap offset)    
190            (declare (ignorable sap offset))
191            ,(unreference-alien
192              type-spec `(,(sap-ref-fname type-spec) sap offset))))))))
193
194
195
196 ;;;;
197
198 (defconstant +bits-per-unit+ 8
199   "Number of bits in an addressable unit (byte)")
200
201 ;; Sizes of fundamental C types in addressable units
202 (defconstant +size-of-short+ 2)
203 (defconstant +size-of-int+ 4)
204 (defconstant +size-of-long+ 4)
205 (defconstant +size-of-sap+ 4)
206 (defconstant +size-of-float+ 4)
207 (defconstant +size-of-double+ 8)
208
209 (defun sap-ref-unsigned (sap offset)
210   (sap-ref-32 sap offset))
211
212 (defun sap-ref-signed (sap offset)
213   (signed-sap-ref-32 sap offset))
214
215 (defun sap-ref-fname (type-spec)
216   (let ((alien-type-spec (mklist (translate-type-spec type-spec))))
217     (ecase (first alien-type-spec)
218       (unsigned
219        (ecase (second alien-type-spec)
220          (8 'sap-ref-8)
221          (16 'sap-ref-16)
222          (32 'sap-ref-32)
223          (64 'sap-ref-64)))
224       (signed
225        (ecase (second alien-type-spec)
226          (8 'signed-sap-ref-8)
227          (16 'signed-sap-ref-16)
228          (32 'signed-sap-ref-32)
229          (64 'signed-sap-ref-64)))
230       (system-area-pointer 'sap-ref-sap)
231       (single-float 'sap-ref-single)
232       (double-float 'sap-ref-double))))
233
234
235 ;;;; Foreign function call interface
236
237 (defvar *package-prefix* nil)
238
239 (defun set-package-prefix (prefix &optional (package *package*))
240   (let ((package (find-package package)))
241     (delete-if #'(lambda (assoc) (eq (car assoc) package)) *package-prefix*)
242     (push (cons package prefix) *package-prefix*))
243   prefix)
244
245 (defun package-prefix (&optional (package *package*))
246   (let ((package (find-package package)))
247     (or
248      (cdr (assoc package *package-prefix*))
249      (substitute #\_ #\- (string-downcase (package-name package))))))
250
251 (defun find-prefix-package (prefix)
252   (or
253    (car (rassoc (string-downcase prefix) *package-prefix* :test #'string=))
254    (find-package (string-upcase prefix))))
255
256 (defmacro use-prefix (prefix &optional (package *package*))
257   `(eval-when (:compile-toplevel :load-toplevel :execute)
258      (set-package-prefix ,prefix ,package)))
259
260
261 (defun default-alien-fname (lisp-name)
262   (let* ((lisp-name-string
263           (if (char= (char (the simple-string (string lisp-name)) 0) #\%)
264               (subseq (the simple-string (string lisp-name)) 1)
265             (string lisp-name)))
266          (prefix (package-prefix *package*))
267          (name (substitute #\_ #\- (string-downcase lisp-name-string))))
268     (if (or (not prefix) (string= prefix ""))
269         name
270       (format nil "~A_~A" prefix name))))
271
272 (defun default-alien-type-name (type-name)
273   (let ((prefix (package-prefix *package*)))
274     (apply
275      #'concatenate
276      'string
277      (mapcar
278       #'string-capitalize    
279       (cons prefix (split-string (symbol-name type-name) #\-))))))
280
281 (defun default-type-name (alien-name)
282   (let ((parts
283          (mapcar
284           #'string-upcase
285           (split-string-if alien-name #'upper-case-p))))
286     (intern
287      (concatenate-strings
288       (rest parts) #\-) (find-prefix-package (first parts)))))
289     
290          
291 (defmacro defbinding (name lambda-list return-type-spec &rest docs/args)
292   (multiple-value-bind (lisp-name c-name)
293       (if (atom name)
294           (values name (default-alien-fname name))
295         (values-list name))
296                        
297     (let ((supplied-lambda-list lambda-list)
298           (docs nil)
299           (args nil))
300       (dolist (doc/arg docs/args)
301         (if (stringp doc/arg)
302             (push doc/arg docs)
303           (progn
304             (destructuring-bind (expr type &optional (style :in)) doc/arg
305               (unless (member style '(:in :out :in-out))
306                 (error "Bogus argument style ~S in ~S." style doc/arg))
307               (when (and
308                      (not supplied-lambda-list)
309                      (namep expr) (member style '(:in :in-out)))
310                 (push expr lambda-list))
311               (push
312                (list (if (namep expr) expr (gensym)) expr type style) args)))))
313       
314       (%defbinding
315        c-name lisp-name (or supplied-lambda-list (nreverse lambda-list))
316        return-type-spec (reverse docs) (reverse args)))))
317
318 #+cmu
319 (defun %defbinding (foreign-name lisp-name lambda-list
320                     return-type-spec docs args)
321   (ext:collect ((alien-types) (alien-bindings) (alien-parameters)
322                 (alien-values) (alien-deallocators))
323     (dolist (arg args)
324       (destructuring-bind (var expr type-spec style) arg
325         (let ((declaration (translate-type-spec type-spec))
326               (deallocation (cleanup-alien type-spec var t)))
327           (cond
328            ((member style '(:out :in-out))
329             (alien-types `(* ,declaration))
330             (alien-parameters `(addr ,var))
331             (alien-bindings
332              `(,var ,declaration
333                ,@(when (eq style :in-out)
334                    (list (translate-to-alien type-spec expr t)))))
335             (alien-values (translate-from-alien type-spec var nil)))
336           (deallocation
337            (alien-types declaration)
338            (alien-bindings
339             `(,var ,declaration ,(translate-to-alien type-spec expr t)))
340            (alien-parameters var)
341            (alien-deallocators deallocation))
342           (t
343            (alien-types declaration)
344            (alien-parameters (translate-to-alien type-spec expr t)))))))
345
346     (let ((alien-funcall `(alien-funcall ,lisp-name ,@(alien-parameters))))
347       `(defun ,lisp-name ,lambda-list
348          ,@docs
349          (with-alien ((,lisp-name
350                        (function
351                         ,(translate-type-spec return-type-spec)
352                         ,@(alien-types))
353                        :extern ,foreign-name)
354                       ,@(alien-bindings))
355            ,(if return-type-spec
356                 `(let ((result
357                         ,(translate-from-alien return-type-spec alien-funcall nil)))
358                    ,@(alien-deallocators)
359                    (values result ,@(alien-values)))
360               `(progn
361                  ,alien-funcall
362                  ,@(alien-deallocators)
363                  (values ,@(alien-values)))))))))
364
365
366 (defun mkbinding (name return-type &rest arg-types)
367    (declare (optimize (ext:inhibit-warnings 3)))
368    (let* ((ftype
369            `(function
370              ,@(mapcar #'translate-type-spec (cons return-type arg-types))))
371          (alien
372           (alien::%heap-alien
373            (alien::make-heap-alien-info
374             :type (alien::parse-alien-type ftype)
375             :sap-form (system:foreign-symbol-address name))))
376          (translate-arguments
377           (mapcar #'intern-return-value-translator arg-types))
378          (translate-return-value (intern-return-value-translator return-type))
379          (cleanup-arguments (mapcar #'intern-cleanup-function arg-types)))
380          
381     #'(lambda (&rest args)
382         (map-into args #'funcall translate-arguments args)
383         (prog1
384             (funcall
385              translate-return-value (apply #'alien:alien-funcall alien args))
386           (mapc #'funcall cleanup-arguments args)))))
387
388
389 (defun type-translateable-p (type-spec)
390   (find-applicable-type-method type-spec 'translate-type-spec nil))
391
392 (defun every-type-translateable-p (type-specs)
393   (every #'type-translateable-p type-specs))
394
395 (defun mkbinding-late (name return-type &rest arg-types)
396   (if (every-type-translateable-p (cons return-type arg-types))
397       (apply #'mkbinding name return-type arg-types)
398     (let* ((binding
399             #'(lambda (&rest args)
400                 (cond
401                  ((every-type-translateable-p (cons return-type arg-types))
402                   (setq binding (apply #'mkbinding name return-type arg-types))
403                   (apply binding args))
404                  (t
405                   (dolist (type-spec (cons return-type arg-types))
406                     (unless (type-translateable-p type-spec)
407                       (error "Can't translate type ~A" type-spec))))))))
408       #'(lambda (&rest args)
409           (apply binding args)))))
410        
411
412   
413
414 ;;;; Definitons and translations of fundamental types
415
416 (deftype long (&optional (min '*) (max '*)) `(integer ,min ,max))
417 (deftype unsigned-long (&optional (min '*) (max '*)) `(integer ,min ,max))
418 (deftype int (&optional (min '*) (max '*)) `(long ,min ,max))
419 (deftype unsigned-int (&optional (min '*) (max '*)) `(unsigned-long ,min ,max))
420 (deftype short (&optional (min '*) (max '*)) `(int ,min ,max))
421 (deftype unsigned-short (&optional (min '*) (max '*)) `(unsigned-int ,min ,max))
422 (deftype signed (&optional (size '*)) `(signed-byte ,size))
423 (deftype unsigned (&optional (size '*)) `(signed-byte ,size))
424 (deftype char () 'base-char)
425 (deftype pointer () 'system-area-pointer)
426 (deftype boolean (&optional (size '*))
427   (declare (ignore size))
428   `(member t nil))
429 (deftype invalid () nil)
430
431 (defun atomic-type-p (type-spec)
432   (or
433    (eq type-spec 'pointer)
434    (not (eq (translate-type-spec type-spec) 'system-area-pointer))))
435
436
437 (deftype-method cleanup-alien t (type-spec sap &optional weak-ref)
438   (declare (ignore type-spec sap weak-ref))
439   nil)
440
441
442 (deftype-method translate-to-alien integer (type-spec number &optional weak-ref)
443   (declare (ignore type-spec weak-ref))
444   number)
445
446 (deftype-method translate-from-alien integer (type-spec number &optional weak-ref)
447   (declare (ignore type-spec weak-ref))
448   number)
449
450
451 (deftype-method translate-type-spec fixnum (type-spec)
452   (declare (ignore type-spec))
453   (translate-type-spec 'signed))
454
455 (deftype-method size-of fixnum (type-spec)
456   (declare (ignore type-spec))
457   (size-of 'signed))
458
459 (deftype-method translate-to-alien fixnum (type-spec number &optional weak-ref)
460   (declare (ignore type-spec weak-ref))
461   number)
462
463 (deftype-method translate-from-alien fixnum (type-spec number &optional weak-ref)
464   (declare (ignore type-spec weak-ref))
465   number)
466
467
468 (deftype-method translate-type-spec long (type-spec)
469   (declare (ignore type-spec))
470   `(signed ,(* +bits-per-unit+ +size-of-long+)))
471
472 (deftype-method size-of long (type-spec)
473   (declare (ignore type-spec))
474   +size-of-long+)
475
476
477 (deftype-method translate-type-spec unsigned-long (type-spec)
478   (declare (ignore type-spec))
479   `(unsigned ,(* +bits-per-unit+ +size-of-long+)))
480
481 (deftype-method size-of unsigned-long (type-spec)
482   (declare (ignore type-spec))
483   +size-of-long+)
484
485
486 (deftype-method translate-type-spec int (type-spec)
487   (declare (ignore type-spec))
488   `(signed ,(* +bits-per-unit+ +size-of-int+)))
489
490 (deftype-method size-of int (type-spec)
491   (declare (ignore type-spec))
492   +size-of-int+)
493
494
495 (deftype-method translate-type-spec unsigned-int (type-spec)
496   (declare (ignore type-spec))
497   `(unsigned ,(* +bits-per-unit+ +size-of-int+)))
498
499 (deftype-method size-of unsigned-int (type-spec)
500   (declare (ignore type-spec))
501   +size-of-int+)
502
503
504 (deftype-method translate-type-spec short (type-spec)
505   (declare (ignore type-spec))
506   `(signed ,(* +bits-per-unit+ +size-of-short+)))
507
508 (deftype-method size-of short (type-spec)
509   (declare (ignore type-spec))
510   +size-of-short+)
511
512
513 (deftype-method translate-type-spec unsigned-short (type-spec)
514   (declare (ignore type-spec))
515   `(unsigned ,(* +bits-per-unit+ +size-of-short+)))
516
517 (deftype-method size-of unsigned-short (type-spec)
518   (declare (ignore type-spec))
519   +size-of-short+)
520
521
522 (deftype-method translate-type-spec signed-byte (type-spec)
523   (let ((size (second (mklist (type-expand-to 'signed-byte type-spec)))))
524     `(signed
525       ,(cond
526         ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+))
527         (t size)))))
528
529 (deftype-method size-of signed-byte (type-spec)
530   (let ((size (second (mklist (type-expand-to 'signed-byte type-spec)))))
531     (cond
532      ((member size '(nil *)) +size-of-int+)
533      (t (/ size +bits-per-unit+)))))
534
535 (deftype-method translate-to-alien signed-byte (type-spec number &optional weak-ref)
536   (declare (ignore type-spec weak-ref))
537   number)
538
539 (deftype-method translate-from-alien signed-byte
540     (type-spec number &optional weak-ref)
541   (declare (ignore type-spec weak-ref))
542   number)
543
544
545 (deftype-method translate-type-spec unsigned-byte (type-spec)
546   (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec)))))
547     `(signed
548       ,(cond
549         ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+))
550         (t size)))))
551
552 (deftype-method size-of unsigned-byte (type-spec)
553   (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec)))))
554     (cond
555      ((member size '(nil *)) +size-of-int+)
556      (t (/ size +bits-per-unit+)))))
557
558 (deftype-method translate-to-alien unsigned-byte (type-spec number &optional weak-ref)
559   (declare (ignore type-spec weak-ref))
560   number)
561
562 (deftype-method translate-from-alien unsigned-byte
563     (type-spec number &optional weak-ref)
564   (declare (ignore type-spec weak-ref))
565   number)
566
567
568 (deftype-method translate-type-spec single-float (type-spec)
569   (declare (ignore type-spec))
570   'single-float)
571
572 (deftype-method size-of single-float (type-spec)
573   (declare (ignore type-spec))
574   +size-of-float+)
575
576 (deftype-method translate-to-alien single-float (type-spec number &optional weak-ref)
577   (declare (ignore type-spec weak-ref))
578   number)
579
580 (deftype-method translate-from-alien single-float
581     (type-spec number &optional weak-ref)
582   (declare (ignore type-spec weak-ref))
583   number)
584
585
586 (deftype-method translate-type-spec double-float (type-spec)
587   (declare (ignore type-spec))
588   'double-float)
589
590 (deftype-method size-of double-float (type-spec)
591   (declare (ignore type-spec))
592   +size-of-double+)
593
594 (deftype-method translate-to-alien double-float (type-spec number &optional weak-ref)
595   (declare (ignore type-spec weak-ref))
596   number)
597
598 (deftype-method translate-from-alien double-float
599     (type-spec number &optional weak-ref)
600   (declare (ignore type-spec weak-ref))
601   number)
602
603
604 (deftype-method translate-type-spec base-char (type-spec)
605   (declare (ignore type-spec))
606   `(unsigned ,+bits-per-unit+))
607
608 (deftype-method size-of base-char (type-spec)
609   (declare (ignore type-spec))
610   1)
611
612 (deftype-method translate-to-alien base-char (type-spec char &optional weak-ref)
613   (declare (ignore type-spec weak-ref))
614   `(char-code ,char))
615
616 (deftype-method translate-from-alien base-char (type-spec code &optional weak-ref)
617   (declare (ignore type-spec weak-ref))
618   `(code-char ,code))
619
620
621 (deftype-method translate-type-spec string (type-spec)
622   (declare (ignore type-spec))
623   'system-area-pointer)
624
625 (deftype-method size-of string (type-spec)
626   (declare (ignore type-spec))
627   +size-of-sap+)
628
629 (deftype-method translate-to-alien string (type-spec string &optional weak-ref)
630   (declare (ignore type-spec weak-ref))
631   `(let ((string ,string))
632      ;; Always copy strings to prevent seg fault due to GC
633      (copy-memory
634       (make-pointer (1+ (kernel:get-lisp-obj-address string)))
635       (1+ (length string)))))
636
637 (deftype-method translate-from-alien string
638     (type-spec c-string &optional weak-ref)
639   (declare (ignore type-spec))
640   `(let ((c-string ,c-string))
641      (unless (null-pointer-p c-string)
642        (prog1
643            (c-call::%naturalize-c-string c-string)
644          ;,(unless weak-ref `(deallocate-memory c-string))
645          ))))
646
647 (deftype-method cleanup-alien string (type-spec c-string &optional weak-ref)
648   (when weak-ref
649     (unreference-alien type-spec c-string)))
650
651 (deftype-method unreference-alien string (type-spec c-string)
652   (declare (ignore type-spec))
653   `(let ((c-string ,c-string))
654      (unless (null-pointer-p c-string)
655        (deallocate-memory c-string))))
656   
657
658 (deftype-method translate-type-spec boolean (type-spec)
659   (translate-type-spec
660    (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec))))))
661
662 (deftype-method size-of boolean (type-spec)
663   (size-of
664    (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec))))))
665
666 (deftype-method translate-to-alien boolean (type-spec boolean &optional weak-ref)
667   (declare (ignore type-spec weak-ref))
668   `(if ,boolean 1 0))
669
670 (deftype-method translate-from-alien boolean (type-spec int &optional weak-ref)
671   (declare (ignore type-spec weak-ref))
672   `(not (zerop ,int)))
673
674
675 (deftype-method translate-type-spec or (union-type)
676   (let* ((member-types (cdr (type-expand-to 'or union-type)))
677          (alien-type (translate-type-spec (first member-types))))
678     (dolist (type (cdr member-types))
679       (unless (eq alien-type (translate-type-spec type))
680         (error "No common alien type specifier for union type: ~A" union-type)))
681     alien-type))
682
683 (deftype-method size-of or (union-type)
684   (size-of (first (cdr (type-expand-to 'or union-type)))))
685
686 (deftype-method translate-to-alien or (union-type-spec expr &optional weak-ref)
687   (destructuring-bind (name &rest type-specs)
688       (type-expand-to 'or union-type-spec)
689     (declare (ignore name))
690     `(let ((value ,expr))
691        (etypecase value
692          ,@(map
693             'list
694               #'(lambda (type-spec)
695                   (list type-spec (translate-to-alien type-spec 'value weak-ref)))
696               type-specs)))))
697
698
699 (deftype-method translate-type-spec system-area-pointer (type-spec)
700   (declare (ignore type-spec))
701   'system-area-pointer)
702
703 (deftype-method size-of system-area-pointer (type-spec)
704   (declare (ignore type-spec))
705   +size-of-sap+)
706
707 (deftype-method translate-to-alien system-area-pointer (type-spec sap &optional weak-ref)
708   (declare (ignore type-spec weak-ref))
709   sap)
710
711 (deftype-method translate-from-alien system-area-pointer
712     (type-spec sap &optional weak-ref)
713   (declare (ignore type-spec weak-ref))
714   sap)
715
716
717 (deftype-method translate-type-spec null (type-spec)
718   (declare (ignore type-spec))
719   'system-area-pointer)
720
721 (deftype-method translate-to-alien null (type-spec expr &optional weak-ref)
722   (declare (ignore type-spec expr weak-ref))
723   `(make-pointer 0))
724
725
726 (deftype-method translate-type-spec nil (type-spec)
727   (declare (ignore type-spec))
728   'void)
729
730 (deftype-method translate-from-alien nil (type-spec expr &optional weak-ref)
731   (declare (ignore type-spec weak-ref))
732   `(progn
733      ,expr
734      (values)))