repos
/
smoke
/ annotate_shade
summary
|
shortlog
|
log
|
tree
|
commit
|
commitdiff
|
headdiff
|
annotate
|
headblob
|
headfilediff
|
filehistory
normal
|
plain
|
shade
|
zebra
SBCL: compile time overload resolution
Annotate for file src/overload-resolution.lisp
2009-04-17 tobias
1
;;; C++ overload resolution
15:26:55 '
2
;;; See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf
'
3
'
4
(in-package :smoke)
'
5
2009-07-22 tobias
6
(defun cstring= (string1 string2)
22:26:05 '
7
"Returns T when the C strings STRING1 and STRING2 are equal
'
8
and NIL otherwise."
'
9
(declare (optimize (speed 3) (safety 0)))
'
10
(dotimes (i array-total-size-limit)
'
11
(let ((char1 (mem-aref string1 :char i))
'
12
(char2 (mem-aref string2 :char i)))
'
13
(when (/= char1 char2)
'
14
(return-from cstring= nil))
'
15
(when (or (= 0 char1)
'
16
(= 0 char2))
'
17
(return-from cstring= (= char1 char2))))))
'
18
2009-06-22 tobias
19
(declaim (inline cmp))
12:18:08 '
20
(defun cmp (a b)
2009-07-22 tobias
21
"Returns -1 if a < b; 0 if a = b and 1 if a > b"
22:26:05 '
22
(declare (values (integer -1 1)))
'
23
(if (< a b)
'
24
-1
'
25
(if (> a b)
'
26
1
'
27
0)))
2009-06-22 tobias
28
2009-07-22 tobias
29
(declaim (inline cstring-cmp))
22:26:05 '
30
(defun cstring-cmp (string1 string2)
'
31
"Compares the C strings STRING1 and STRING2."
'
32
(declare (foreign-pointer string1 string2)
'
33
(values (integer -1 1))
'
34
(optimize (speed 3)))
'
35
(dotimes (i array-total-size-limit (error "omg"))
'
36
(let ((char1 (mem-aref string1 :char i))
'
37
(char2 (mem-aref string2 :char i)))
'
38
(when (/= char1 char2)
'
39
(return-from cstring-cmp (if (< char1 char2) -1 1)))
'
40
(when (= 0 char1) ;; <=> (= 0 char2)
'
41
(return-from cstring-cmp 0)))))
2009-04-17 tobias
42
2009-06-22 tobias
43
(defun cstring/= (string1 string2)
12:18:08 '
44
"Returns T when the C strings STRING1 and STRING2 are not equal
'
45
and NIL otherwise."
2009-07-22 tobias
46
(declare (optimize (speed 3)))
22:26:05 '
47
(dotimes (i array-total-size-limit)
'
48
(let ((char1 (mem-aref string1 :char i))
'
49
(char2 (mem-aref string2 :char i)))
'
50
(when (/= char1 char2)
'
51
(return-from cstring/= i))
'
52
(when (= 0 char1)
'
53
(return-from cstring/= nil)))))
'
54
'
55
(declaim (inline smoke-method-name))
'
56
(defun smoke-method-name (method)
'
57
(mem-aref (smoke-array-pointer (smoke-module-method-names
'
58
(smoke-method-smoke method)))
'
59
:pointer
'
60
(the (smoke-index 0)
'
61
(method-slot-value method 'name))))
2009-04-17 tobias
62
2009-06-22 tobias
63
(defun method-cmp (method class-id name)
12:18:08 '
64
"Compares METHOD to the method with NAME of class CLASS-ID."
'
65
(declare (foreign-pointer name)
'
66
(type (smoke-index 0) class-id)
'
67
(smoke-method method)
2009-07-22 tobias
68
(values (integer -1 1))
2009-06-22 tobias
69
(optimize (speed 3) (debug 0) (safety 0)))
12:18:08 '
70
(let ((id-cmp (cmp (the (smoke-index 0) (method-slot-value method 'class))
'
71
(the (smoke-index 0) class-id))))
2009-07-22 tobias
72
(declare (type (integer -1 1) id-cmp)
22:26:05 '
73
(dynamic-extent id-cmp))
2009-06-22 tobias
74
(if (/= 0 id-cmp)
12:18:08 '
75
id-cmp
2009-07-22 tobias
76
(cstring-cmp (smoke-method-name method)
2009-06-22 tobias
77
name))))
12:18:08 '
78
'
79
(defun first-unabigious-index (smoke index)
'
80
(declare (type smoke-index index)
2009-04-17 tobias
81
(optimize (speed 3)))
2009-06-22 tobias
82
(if (>= index 0)
12:18:08 '
83
index
'
84
(mem-aref (smoke-module-ambiguous-method-list smoke)
'
85
'smoke-index
'
86
(- index))))
2009-04-17 tobias
87
2009-06-22 tobias
88
(defun find-method-for-class (name class)
12:18:08 '
89
"Returns the index of a method with name NAME for class CLASS."
'
90
(declare (type foreign-pointer name)
'
91
(type smoke-class class)
'
92
(optimize (speed 3)))
'
93
(let* ((start 1) ;; 0 is "no method"
2009-06-30 tobias
94
(class-id (id class))
22:47:39 '
95
(smoke (smoke class))
2009-07-03 tobias
96
(end (1+ (smoke-array-length (smoke-module-method-maps smoke)))))
2009-07-08 tobias
97
(declare (type (smoke-index 0) start end))
2009-06-22 tobias
98
(loop until (> start end) do
12:18:08 '
99
(let* ((index (the smoke-index (floor (+ end start) 2)))
'
100
(method (make-smoke-method
'
101
:smoke smoke
'
102
:id (the (smoke-index 0)
'
103
(first-unabigious-index
'
104
smoke
'
105
(foreign-slot-value
'
106
(mem-aref (smoke-array-pointer
'
107
(smoke-module-method-maps
'
108
smoke))
'
109
'smoke-method-map index)
'
110
'smoke-method-map
'
111
'method)))))
2009-07-22 tobias
112
(cmp (the (integer -1 1) (method-cmp method class-id name))))
22:26:05 '
113
(declare (type (integer -1 1) cmp)
2009-07-08 tobias
114
(dynamic-extent method index cmp))
2009-07-22 tobias
115
(ecase cmp
22:26:05 '
116
(-1 (setf start (1+ index)))
'
117
(0 (return-from find-method-for-class index))
'
118
(1 (setf end (1- index)))))))
2009-06-22 tobias
119
-1)
2009-04-17 tobias
120
2009-08-27 tobias
121
(defmacro push-candidate-method (index name argument-count class methods)
2009-06-22 tobias
122
(with-gensyms (method-map method-index method ambig-index i smoke)
12:18:08 '
123
`(let* ((,smoke (smoke ,class))
'
124
(,method-map (mem-aref
'
125
(smoke-array-pointer
'
126
(smoke-module-method-maps ,smoke))
'
127
'smoke-method-map
2009-07-22 tobias
128
,index))
2009-06-22 tobias
129
(,method-index (foreign-slot-value ,method-map 'smoke-method-map 'method))
12:18:08 '
130
(,method (make-smoke-method
'
131
:smoke ,smoke
'
132
:id (first-unabigious-index
'
133
,smoke
'
134
,method-index))))
'
135
(declare (type smoke-index ,method-index))
'
136
(if (cstring/= ,name
'
137
(smoke-method-name ,method))
'
138
nil
'
139
(progn
'
140
(when (= (the smoke-index ,argument-count)
'
141
(the smoke-index (get-arguments-length ,method)))
'
142
(if (< ,method-index 0)
'
143
(let ((,ambig-index (- ,method-index)))
'
144
(declare (type smoke-index ,ambig-index))
'
145
(loop as ,i = (the smoke-index
'
146
(mem-aref (smoke-module-ambiguous-method-list
'
147
,smoke)
'
148
'smoke-index
'
149
,ambig-index))
'
150
while (> (the smoke-index ,i) 0) do
2009-08-27 tobias
151
(incf ,ambig-index)
11:43:13 '
152
(push (make-smoke-method :smoke ,smoke
'
153
:id ,i)
'
154
,methods)))
'
155
(push ,method ,methods)))
2009-06-22 tobias
156
t)))))
2009-05-11 tobias
157
2009-08-30 tobias
158
(defun all-smoke-superclasses (class)
14:12:44 '
159
"Returns a list of all super-classes of CLASS and CLASS itself."
'
160
(declare (optimize (speed 3)))
'
161
(let ((classes (list class)))
'
162
(dolist (class (closer-mop:class-direct-superclasses class) classes)
'
163
(when (typep class 'smoke-standard-class)
'
164
(setf classes (append (all-smoke-superclasses class) classes))))))
'
165
2009-08-27 tobias
166
(defun viable-functions (name argument-count class)
11:43:13 '
167
"Returns a list of methods named NAME that take ARGUMENT-COUNT methods."
'
168
;; 13.3.2
'
169
;; FIXME make a lazy map-viable-functions to allow returning early,
'
170
;; when an exact match is found.
2009-06-22 tobias
171
(declare (optimize (speed 3)))
12:18:08 '
172
(with-foreign-string (name name)
2009-07-22 tobias
173
(let ((methods)
22:26:05 '
174
(smoke (smoke class)))
2009-08-27 tobias
175
(dolist (class (all-smoke-superclasses class))
2009-07-22 tobias
176
(let ((start-index (find-method-for-class name class)))
22:26:05 '
177
(declare (type smoke-index start-index))
'
178
(loop for index from start-index downto 1
'
179
while (push-candidate-method index name argument-count class
'
180
methods))
'
181
(loop for index from (1+ start-index)
'
182
to (the smoke-index (smoke-array-length
'
183
(smoke-module-method-maps smoke)))
'
184
while (push-candidate-method index name argument-count class
'
185
methods))))
2009-06-22 tobias
186
methods)))
12:18:08 '
187
2009-07-22 tobias
188
(eval-when (:compile-toplevel :load-toplevel :execute)
22:26:05 '
189
(defconstant +exact-match+ 0)
'
190
(defconstant +promotion+ 1)
'
191
(defconstant +conversion+ 2))
'
192
2009-07-08 tobias
193
(defclass std-conversion ()
20:41:19 '
194
((function-name :accessor conversion-function-name
'
195
:initarg :conversion-function-name))
'
196
(:documentation "A conversion"))
2009-04-17 tobias
197
2009-07-08 tobias
198
(defclass exact-match (std-conversion)
20:41:19 '
199
((rank :reader rank
'
200
:allocation :class
'
201
:type fixnum
'
202
:initform +exact-match+)))
2009-04-17 tobias
203
2009-07-08 tobias
204
(defclass promotion (std-conversion)
20:41:19 '
205
((rank :reader rank
'
206
:allocation :class
'
207
:type fixnum
'
208
:initform +promotion+)))
2009-04-17 tobias
209
2009-07-08 tobias
210
(defclass number-conversion (std-conversion)
20:41:19 '
211
((rank :reader rank
'
212
:allocation :class
'
213
:type fixnum
'
214
:initform +conversion+)))
2009-04-17 tobias
215
2009-07-08 tobias
216
(defclass pointer-conversion (std-conversion)
20:41:19 '
217
((rank :reader rank
'
218
:allocation :class
'
219
:type fixnum
'
220
:initform (1+ +conversion+))
'
221
(from :reader from
'
222
:initarg :from)
'
223
(to :reader to
'
224
:initarg :to)))
2009-04-17 tobias
225
2009-07-08 tobias
226
(defclass boolean-conversion (std-conversion)
20:41:19 '
227
((rank :reader rank
'
228
:allocation :class
'
229
:type fixnum
'
230
:initform (+ 2 +conversion+))))
2009-04-17 tobias
231
2009-07-08 tobias
232
(defclass user-conversion (std-conversion)
20:41:19 '
233
((rank :reader rank
'
234
:allocation :class
'
235
:type fixnum
'
236
:initform (+ 3 +conversion+))))
2009-04-17 tobias
237
2009-08-27 tobias
238
(defgeneric conversion< (conversion1 conversion2)
11:43:13 '
239
(:documentation
'
240
"Returns true when CONVERSION1 is better than CONVERSION2.")
2009-04-17 tobias
241
;; 13.3.3.2 Ranking implicit conversion sequences
15:26:55 '
242
;; 4
'
243
(:method (conversion1 conversion2)
2009-06-22 tobias
244
(declare (optimize (speed 3)))
2009-08-27 tobias
245
(or (null conversion2)
2009-07-08 tobias
246
(< (the fixnum (rank conversion1))
20:41:19 '
247
(the fixnum (rank conversion2)))))
2009-04-17 tobias
248
(:method ((conversion1 pointer-conversion) (conversion2 pointer-conversion))
2009-06-22 tobias
249
(declare (optimize (speed 3)))
2009-07-08 tobias
250
(if (eq (from conversion1) (from conversion2))
2009-04-17 tobias
251
;; A->B < A->C <=> B subclass of C
2009-07-08 tobias
252
(subtypep (to conversion1) (to conversion2))
20:41:19 '
253
(if (eq (to conversion1) (to conversion2))
2009-04-17 tobias
254
;; B->A < C->A <=> B subclass of C
2009-07-08 tobias
255
(subtypep (from conversion1) (from conversion2))
2009-04-17 tobias
256
nil))))
15:26:55 '
257
'
258
(defgeneric conversion= (conversion1 conversion2)
2009-08-27 tobias
259
(:documentation
11:43:13 '
260
"Returns true when the standard conversion sequence CONVERSION1
'
261
is indistinguishable from CONVERSION2.")
2009-04-17 tobias
262
(:method (conversion1 conversion2)
2009-07-08 tobias
263
(= (rank conversion1) (rank conversion2)))
2009-05-11 tobias
264
(:method ((conversion1 (eql nil)) (conversion2 (eql nil)))
2009-07-22 tobias
265
t)
22:26:05 '
266
(:method ((conversion1 pointer-conversion) (conversion2 pointer-conversion))
'
267
(and (not (conversion< conversion1 conversion2))
'
268
(not (conversion< conversion2 conversion1)))))
2009-04-17 tobias
269
15:26:55 '
270
(defun max-conversion (conversion1 conversion2)
2009-05-11 tobias
271
"Returns the greater conversion of CONVERSION1 and CONVERSION2."
2009-04-17 tobias
272
(if (null conversion2)
15:26:55 '
273
conversion1
2009-08-27 tobias
274
(if (conversion< conversion1 conversion2)
2009-04-17 tobias
275
conversion2
15:26:55 '
276
conversion1)))
2009-05-11 tobias
277
2010-02-20 tobias
278
(eval-when (:compile-toplevel :load-toplevel :execute)
17:24:36 '
279
(defun conversion-function (name &optional arg)
'
280
(if arg
'
281
`(if (using-typep)
'
282
`(,,name
'
283
(find-class ',(class-name ,arg)))
'
284
#'(lambda (object)
'
285
(funcall (fdefinition ,name)
'
286
object ,arg)))
'
287
`(if (using-typep)
'
288
,name
'
289
(fdefinition ,name)))))
'
290
2009-09-01 tobias
291
(defmacro make-match (type &optional (name ''identity)
11:44:21 '
292
(argument nil)
2009-05-11 tobias
293
&rest args)
2009-07-08 tobias
294
`(make-instance ,type
20:41:19 '
295
:conversion-function-name ,(conversion-function name argument)
'
296
2009-09-01 tobias
297
,@args))
2009-04-17 tobias
298
2009-05-11 tobias
299
(defun+using-type get-conversion-sequence object (object type &optional user)
2009-07-01 tobias
300
"Retrains a conversion sequence to convert a instance of type CLASS
2009-05-11 tobias
301
to an instance of type TYPE. When USER is true user conversions are considered."
2009-07-08 tobias
302
(if-let (match (call-using-type exact-match object type))
14:56:52 '
303
(if (eql t match)
'
304
(make-match 'exact-match)
'
305
(make-match 'exact-match match))
'
306
(or (call-using-type promotion object type)
'
307
(call-using-type conversion object type)
'
308
(and user
'
309
(call-using-type user-conversion object type)))))
2009-04-17 tobias
310
2009-05-11 tobias
311
(defun+using-types standard-conversion-sequence (method classes &optional user)
11:07:39 '
312
"Returns the conversion sequences to convert the arguments of types CLASSES
'
313
to the types required by METHOD."
2009-08-27 tobias
314
(let ((max-rank)
11:43:13 '
315
(conversions))
'
316
(loop for type in (arguments method)
'
317
for class in classes do
'
318
(let ((rank (call-using-type get-conversion-sequence class type user)))
'
319
(when (null rank)
'
320
(setf max-rank nil)
'
321
(return nil))
'
322
(setf max-rank (max-conversion rank max-rank))
'
323
(push (conversion-function-name rank) conversions)))
'
324
(values max-rank (reverse conversions))))
2009-04-17 tobias
325
2009-05-11 tobias
326
(defun+using-types conversion-sequence (method classes)
11:07:39 '
327
(call-using-types standard-conversion-sequence method classes t))
2009-04-17 tobias
328
2009-08-27 tobias
329
(defun+using-types find-best-viable-function (name arguments class)
2009-05-11 tobias
330
"Returns the method named NAME of class CLASS that can be called
11:07:39 '
331
using arguments of types TYPES with the lowest conversion sequence."
'
332
(call-using-types find-best-viable-function2
'
333
(function-using-types conversion-sequence)
2009-08-27 tobias
334
name arguments class))
2009-04-17 tobias
335
2009-08-27 tobias
336
(defun+using-types find-best-viable-function2 (get-sequence name objects class)
11:43:13 '
337
(declare (type (function (t list) (values t function)) get-sequence))
2009-05-11 tobias
338
(when (and (using-typep)
11:07:39 '
339
(not (typep class 'smoke-standard-class)))
'
340
(throw 'unspecific-type class))
2009-05-11 tobias
341
(let ((viable-functions (viable-functions name (length objects)
2009-08-27 tobias
342
class))
2009-05-11 tobias
343
(best-rank)
2009-04-17 tobias
344
(best-method)
15:26:55 '
345
(conversions))
2009-08-27 tobias
346
(loop for method in viable-functions do
11:43:13 '
347
(multiple-value-bind (rank method-conversions)
'
348
(funcall get-sequence method objects)
'
349
;; FIXME test for ambiguous overload #'conversion=
'
350
(when (and rank (conversion< rank best-rank))
'
351
(setf best-rank rank)
'
352
(setf best-method method)
'
353
(setf conversions method-conversions)
'
354
(when (conversion= rank (make-match 'exact-match))
'
355
(return)))))
'
356
(values best-method conversions)))
2009-04-17 tobias
357
2009-05-11 tobias
358
(defvar *from-lisp-translations* (make-hash-table :test 'equal))
11:07:39 '
359
'
360
(defmacro define-from-lisp-translation (type-names lisp-type
'
361
&optional
'
362
(conversion-function-name 'identity))
2009-05-11 tobias
363
"Defines a translation from LISP-TYPE to the C++ types TYPE-NAMES using
14:11:35 '
364
the function CONVERSION-FUNCTION-NAME."
2009-05-11 tobias
365
`(progn ,@(loop for type-name in (ensure-list type-names)
2009-05-11 tobias
366
collect `(setf (gethash ,type-name *from-lisp-translations*)
2009-09-02 tobias
367
#'(lambda (type)
11:49:34 '
368
(and (subtypep type ',lisp-type)
2009-05-11 tobias
369
',conversion-function-name))))))
11:07:39 '
370
'
371
(define-from-lisp-translation ("void*" "const void*" "void**" "const void**")
'
372
foreign-pointer)
'
373
'
374
;; FIXME grovel this?
'
375
(deftype c-integer (ctype)
'
376
(let ((bits (* 8 (foreign-type-size ctype))))
2009-05-11 tobias
377
(if (starts-with-subseq
2009-05-11 tobias
378
(symbol-name :unsigned)
11:07:39 '
379
(symbol-name ctype))
'
380
`(unsigned-byte ,bits)
'
381
`(signed-byte ,bits))))
'
382
'
383
'
384
(defun+using-type exact-match object (object type)
'
385
"Test for an exact match."
2009-04-17 tobias
386
(case (type-id type)
2009-06-22 tobias
387
(0 (when-let (test (gethash (name type) *from-lisp-translations*))
2009-09-02 tobias
388
(funcall test (object.type-of))))
2009-05-11 tobias
389
(1 (object.typep 'boolean))
11:07:39 '
390
(2 (object.typep 'standard-char))
'
391
(3 (object.typep '(c-integer :unsigned-char)))
'
392
(4 (object.typep '(c-integer :short)))
'
393
(5 (object.typep '(c-integer :unsigned-short)))
'
394
(6 (object.typep '(c-integer :int)))
'
395
(7 (object.typep '(c-integer :unsigned-int)))
'
396
(10 (object.typep 'single-float))
'
397
(11 (object.typep 'double-float))
2010-01-25 tobias
398
(12 (object.typep 'enum)) ;; FIXME enum-type
2009-09-09 tobias
399
(13 (and (object.typep 'smoke-standard-object)
13:22:32 '
400
(smoke-type= (get-class type) (object.type-of))))))
2009-05-11 tobias
401
11:07:39 '
402
'
403
(defun make-cleanup-pointer (pointer cleanup-function)
2009-05-26 tobias
404
"Returns a pointer that calls CLEANUP-FUNCTION with pointer as argument
09:54:47 '
405
when it is finalized."
2009-05-11 tobias
406
(let ((address (pointer-address pointer)))
11:07:39 '
407
(tg:finalize pointer #'(lambda ()
'
408
(funcall cleanup-function
'
409
(make-pointer address))))))
'
410
2009-04-17 tobias
411
(defun make-auto-pointer (pointer)
15:26:55 '
412
"Returns a pointer that frees the memory at POINTER when it is finalized."
2009-05-26 tobias
413
(make-cleanup-pointer pointer #'foreign-free))
2009-04-17 tobias
414
2009-05-11 tobias
415
(defun coerce-c-string (string)
11:07:39 '
416
(make-auto-pointer (foreign-string-alloc string)))
'
417
2010-02-20 tobias
418
(defun coerce-enum (enum)
2009-05-11 tobias
419
(cxx-support:value enum))
11:07:39 '
420
2009-07-02 tobias
421
(defun coerce-double-float (number)
21:51:50 '
422
(float number 0d0))
'
423
'
424
;; FIXME incomplete
2009-05-11 tobias
425
(defun+using-type promotion object (object type)
2009-04-17 tobias
426
(declare (smoke-type type))
15:26:55 '
427
(case (type-id type)
2009-05-11 tobias
428
(0 (when (and (string= (name type) "const char*")
11:07:39 '
429
(object.typep 'string))
'
430
(make-match 'promotion 'coerce-c-string)))
'
431
(6 (when (object.typep 'enum)
2010-02-20 tobias
432
(make-match 'promotion 'coerce-enum)))
2009-05-11 tobias
433
(7 (when (object.typep 'enum)
2010-02-20 tobias
434
(make-match 'promotion 'coerce-enum)))
2009-07-02 tobias
435
(11 (when (object.typep 'real)
2010-02-20 tobias
436
(make-match 'promotion 'coerce-double-float)))))
2009-04-17 tobias
437
2009-05-26 tobias
438
(declaim (inline coerce-to-class))
2009-05-11 tobias
439
(defun coerce-cast (object to-class)
11:07:39 '
440
(cast object to-class))
2009-04-17 tobias
441
2009-05-11 tobias
442
(defun coerce-to-void (object)
11:07:39 '
443
object)
2009-04-17 tobias
444
2009-05-11 tobias
445
(defun+using-type conversion-cast object (object type)
11:07:39 '
446
(when (and (class-p type)
'
447
(object.typep 'smoke-standard-object)
2009-08-27 tobias
448
(derived-p (object.type-of) (get-class type)))
2009-05-11 tobias
449
(make-match 'pointer-conversion
11:07:39 '
450
'coerce-cast
'
451
(find-smoke-class (get-class type))
'
452
:from (object.type-of)
'
453
:to (find-smoke-class (get-class type)))))
'
454
'
455
(defun+using-type conversion-void object (object type)
'
456
(when (and (string= (name type) "void*")
'
457
(object.typep 'smoke-standard-object))
'
458
(make-match 'pointer-conversion
'
459
'coerce-void
'
460
nil
'
461
:from (object.type-of)
'
462
:to (find-class 't))))
'
463
'
464
(defun+using-type conversion-pointer object (object type)
2009-07-22 tobias
465
;; Not using pointer-p to allow passing a raw pointer for
22:26:05 '
466
;; objects on the stack and references
2009-05-24 tobias
467
;; (e.g.: for qInstallMsgHandler(QtMsgHandler) )
21:28:44 '
468
;;
2009-07-22 tobias
469
;; FIXME this breaks passing pointers to references
22:26:05 '
470
;; e.g.: calling the function foo(QByteArray& foo)
'
471
;; with (foo pointer) assumes pointer to point to a QByteArray,
'
472
;; but actually the conversion sequence QByteArray(pointer) should be used.
'
473
;; When pointer is a null pointer it fails horribly!.
2009-05-24 tobias
474
(when (and (or (= 0 (type-id type)) ; voidp
21:28:44 '
475
(= 13 (type-id type))) ; class
2009-05-11 tobias
476
(object.typep 'foreign-pointer))
11:07:39 '
477
(make-match 'pointer-conversion 'identity nil
2009-08-02 tobias
478
:from (find-class 't)
10:12:41 '
479
:to (find-class 't)))) ;; FIXME get the class when applicable
2009-05-11 tobias
480
11:07:39 '
481
'
482
(defun+using-type conversion object (object type)
'
483
(or (call-using-type conversion-cast object type)
'
484
(call-using-type conversion-void object type)
'
485
(call-using-type conversion-pointer object type)))
'
486
'
487
(defun+using-type user-conversion object (object type)
'
488
(or (call-using-type operator-conversion object type)
'
489
(call-using-type constructor-conversion object type)))
'
490
'
491
(defun+using-type operator-conversion object (object type)
'
492
(when (object.typep 'smoke-standard-object)
'
493
(let ((method (find-smoke-method (object.type-of)
2009-07-24 tobias
494
(format nil "operator ~A"
13:32:23 '
495
(if (class-p type)
'
496
(name (get-class type))
'
497
(name type))))))
2009-05-11 tobias
498
(when (valid-p method)
2009-08-27 tobias
499
(assert (not (void-p type))
11:43:13 '
500
()
'
501
"Conversion operators not supported by Smoke.
'
502
Update to Smoke >= r955426.")
2009-07-24 tobias
503
(make-match 'user-conversion
13:32:23 '
504
(lispify (name method) :cxx))))))
2009-05-11 tobias
505
2009-05-26 tobias
506
(declaim (inline coerce-to-class))
2009-05-11 tobias
507
(defun coerce-to-class (object to-class)
11:07:39 '
508
(make-instance to-class
'
509
:args (list object)))
'
510
'
511
(defun+using-type constructor-conversion object (object type)
'
512
(when (class-p type)
2009-08-27 tobias
513
(let ((to-class (find-smoke-class (get-class type))))
11:43:13 '
514
(when (call-using-types find-best-viable-function2
'
515
(if (using-typep)
'
516
#'standard-conversion-sequence-using-types
'
517
#'standard-conversion-sequence)
2009-07-22 tobias
518
(format nil "~A" (name (get-class type)))
2009-08-27 tobias
519
(list object) to-class)
2010-01-10 tobias
520
(make-match 'user-conversion
17:31:42 '
521
'coerce-to-class
'
522
to-class)))))
2009-04-17 tobias
523
15:26:55 '
524
(defun call-sequence (method object sequence &rest args)
'
525
(s-call method object
2009-05-11 tobias
526
(mapcar #'(lambda (conversion argument)
11:07:39 '
527
(funcall conversion argument))
'
528
sequence args)))
2009-05-27 tobias
529
17:47:28 '
530
(defun format-no-applicable-cxx-method (stream name class arguments)
'
531
(format stream
'
532
"No applicable method ~S of ~A for ~S.
2009-07-02 tobias
533
Candidates are:~{~T~A~%~}."
2009-05-27 tobias
534
name class arguments
17:47:28 '
535
(mapcar #'signature
'
536
(viable-functions name
'
537
(length arguments)
'
538
(smoke-class-of class)))))
'
539
'
540
(define-condition no-applicable-cxx-method (error)
'
541
((method :initarg :method :reader condition-method)
'
542
(class :initarg :class :reader condition-class)
'
543
(arguments :initarg :arguments :reader condition-arguments))
'
544
(:report (lambda (condition stream)
'
545
(format-no-applicable-cxx-method stream
'
546
(condition-method condition)
'
547
(condition-class condition)
'
548
(condition-arguments condition)))))
2009-09-01 tobias
549
2009-04-17 tobias
550
(defun call-using-args (object-or-class name arguments)
2009-06-22 tobias
551
"Calls the method NAME of OBJECT-OR-CLASS with ARGUMENTS."
2009-09-09 tobias
552
(declare (optimize (speed 3)))
2009-08-27 tobias
553
(if (null arguments)
11:43:13 '
554
(let ((method (find-smoke-method (smoke-class-of object-or-class)
'
555
name)))
'
556
(unless (valid-p method)
'
557
(error (make-condition 'no-applicable-cxx-method
'
558
:method name
'
559
:class object-or-class
'
560
:arguments arguments)))
'
561
(if (static-p method)
'
562
(s-call method (null-pointer))
'
563
(s-call method (cast object-or-class (get-class method)))))
'
564
(multiple-value-bind (method sequence)
'
565
(find-best-viable-function name
'
566
arguments
'
567
(smoke-class-of object-or-class))
'
568
(when (null method)
'
569
(error (make-condition 'no-applicable-cxx-method
'
570
:method name
'
571
:class object-or-class
'
572
:arguments arguments)))
'
573
(if (static-p method)
'
574
(apply #'call-sequence method (null-pointer) sequence arguments)
'
575
(apply #'call-sequence method (cast object-or-class (get-class method))
'
576
sequence arguments)))))