1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
;;;; Objective-CL, an Objective-C bridge for Common Lisp.
;;;; Copyright (C) 2007, 2008 Matthias Andreas Benkard.
;;;;
;;;; This program is free software: you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public License
;;;; as published by the Free Software Foundation, either version 3 of
;;;; the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful, but
;;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this program. If not, see
;;;; <http://www.gnu.org/licenses/>.
(in-package #:objective-cl)
(defclass objective-c-generic-function (standard-generic-function)
()
(:metaclass funcallable-standard-class))
(defclass objective-c-method (standard-method)
((return-type :initarg :return-type
:accessor method-return-type)
(argument-types :initarg :argument-types
:accessor method-argument-types))
(:metaclass standard-class))
(defun qualifiers-return-type (qualifiers)
(find-if #'(lambda (x)
(or (not (keywordp x))
(typep x 'objective-c-type-keyword)))
qualifiers))
(defmacro define-objective-c-method (name &rest args)
(let ((qualifiers (list)))
(loop until (listp (first args))
do (push (pop args) qualifiers))
(setq qualifiers (nreverse qualifiers))
(destructuring-bind (lambda-list . body) args
(let ((lambda-list (copy-list lambda-list)))
(loop for arg-cons on lambda-list
for arg = (car arg-cons)
until (member arg lambda-list-keywords)
if (listp arg)
if (typep (second arg) 'objective-c-type-keyword)
collect (second arg) into type-specifiers
and do (setf (car arg-cons) (first arg))
else
;; We simply map all non-OBJECTIVE-C-TYPE-KEYWORD
;; specialisers to :ID. This makes sense: If the
;; specialiser is an Objective-C type, the type
;; specifier should obviously be :ID. If it's a
;; non-Objective-C CLOS class, we're going to pass
;; Objective-C objects of the LISP-VALUE-WRAPPER-MIXIN
;; kind to the method, whose type specifier is :ID as
;; well.
collect :id into type-specifiers
else
collect :id into type-specifiers
finally (return
`(defmethod ,name
argtypes-start ,@type-specifiers argtypes-end
,@qualifiers ,lambda-list
,@body)))))))
(defmethod add-method :after ((gf objective-c-generic-function)
(method objective-c-method))
#+(or) (format t "~&ADD-METHOD:~& ~A, ~A" gf method))
(defmethod initialize-instance :around ((method objective-c-method)
&rest initargs
&key documentation
function
lambda-list
qualifiers
specializers
&allow-other-keys)
(declare (ignore documentation function lambda-list specializers))
#+(or) (format t "~&INITIALIZE-INSTANCE:~& ~S" initargs)
(let* ((argtypes-start (position 'argtypes-start qualifiers))
(argtypes-end (position 'argtypes-end qualifiers))
(argument-types (subseq qualifiers (1+ argtypes-start) argtypes-end))
(qualifiers (append (subseq qualifiers 0 argtypes-start)
(subseq qualifiers (1+ argtypes-end))))
(new-initargs (copy-list initargs))
(return-type (qualifiers-return-type qualifiers)))
(setf (getf new-initargs :qualifiers) (remove return-type qualifiers))
(apply #'call-next-method
method
:return-type (or return-type :id)
:argument-types argument-types
new-initargs)))
#+(or)
(defgeneric bla (x y z &rest r)
(:generic-function-class objective-c-generic-function)
(:method-class objective-c-method))
#+(or)
(defmethod bla :abc ((x number) (y symbol) c &rest r)
(declare (ignore c r))
(+ x 3))
|