forked from quil-lang/sbcl-librarian
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunction.lisp
82 lines (78 loc) · 3.71 KB
/
function.lisp
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
(in-package #:sbcl-librarian)
(defvar *initialize-callables-p* nil
"Bound to T when we are loading Lisp and want to reinitialize
callables on load.")
(defun canonical-signature (name result-type typed-lambda-list &key
(function-prefix "")
error-map)
(let* ((callable-name (prefix-name function-prefix name))
(return-type
(if error-map
(error-map-type error-map)
result-type))
(use-result-arg
(and error-map
(not (eq result-type ':void)))))
(values callable-name
return-type
typed-lambda-list
(and use-result-arg result-type))))
(defun c-function-declaration (name result-type typed-lambda-list &key
(datap 't)
(linkage nil)
(function-prefix "")
error-map)
(multiple-value-bind (callable-name return-type typed-lambda-list result-type)
(canonical-signature name result-type typed-lambda-list
:function-prefix function-prefix
:error-map error-map)
(format nil "~@[~a ~]~a ~:[~a~;(*~a)~](~{~a~^, ~})"
linkage
(c-type return-type)
datap
(coerce-to-c-name callable-name)
(append
(mapcar (lambda (item)
(destructuring-bind (name type)
item
(format nil "~a ~a" (c-type type) (lisp-to-c-name name))))
typed-lambda-list)
(and result-type
(list (format nil "~a *result" (c-type result-type))))))))
(defun callable-definition (name result-type typed-lambda-list &key
(function-prefix "")
error-map)
(let ((bindings
(mapcar (lambda (item)
(destructuring-bind (arg type)
item
(list (gensym)
(funcall (alien-to-lisp type) arg))))
typed-lambda-list)))
(multiple-value-bind (callable-name return-type typed-lambda-list result-type)
(canonical-signature name
result-type
typed-lambda-list
:function-prefix function-prefix
:error-map error-map)
`(progn
(sb-alien:define-alien-callable
,callable-name
,(sb-alien-type return-type)
(,@(loop :for (arg type) :in typed-lambda-list
:collect (list arg (sb-alien-type type)))
,@(when result-type
`((result (* ,(sb-alien-type result-type))))))
(let ,bindings
,(let* ((wrapped
(funcall (lisp-to-alien (or result-type return-type))
`(,(if (listp name) (second name) name) ,@(mapcar #'first bindings))))
(result
(if result-type
`(setf (sb-alien:deref result) ,wrapped)
wrapped)))
(if error-map
(wrap-error-handling result error-map)
result))))
(when *initialize-callables-p*
(sb-alien::initialize-alien-callable-symbol ',name))))))