type-specific wrapping and unwrapping of scheme values
[clinton/guile-figl.git] / figl / runtime.scm
CommitLineData
8925f36f
AW
1;;; figl
2;;; Copyright (C) 2013 Andy Wingo <wingo@pobox.com>
3;;;
4;;; Figl is free software: you can redistribute it and/or modify it
5;;; under the terms of the GNU Lesser General Public License as
6;;; published by the Free Software Foundation, either version 3 of the
7;;; License, or (at your option) any later version.
8;;;
9;;; Figl is distributed in the hope that it will be useful, but WITHOUT
10;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12;;; Public License for more details.
13;;;
14;;; You should have received a copy of the GNU Lesser General Public
15;;; License along with this program. If not, see
16;;; <http://www.gnu.org/licenses/>.
17
18;;; Commentary:
19;;
20;; figl is the Foreign Interface to GL.
21;;
22;;; Code:
23
7ec693ed 24(define-module (figl runtime)
e9dbe4b7 25 #:use-module (system foreign)
7ec693ed 26 #:export (current-resolver
f53f928c 27 define-foreign-procedure
93f72ad8
AW
28 define-foreign-procedures
29 define-foreign-type
30 define-simple-foreign-type))
b59ebd7a 31
7ec693ed 32(define (default-resolver name)
542ee4ba
AW
33 (dynamic-pointer name (dynamic-link)))
34
7ec693ed
AW
35(define current-resolver
36 (make-parameter default-resolver))
8925f36f 37
7ec693ed
AW
38(define (resolve name)
39 ((current-resolver) name))
e9dbe4b7
AW
40
41(define-syntax foreign-trampoline
42 (lambda (stx)
43 (syntax-case stx (->)
44 ((_ trampoline
45 name (pname ptype) ... -> type)
46 (with-syntax ((sname (symbol->string (syntax->datum #'name))))
47 #'(lambda (pname ...)
7ec693ed 48 (let ((ptr (resolve sname)))
e9dbe4b7 49 (set! trampoline
93f72ad8 50 (pointer->procedure (type)
e9dbe4b7 51 ptr
93f72ad8 52 (list (ptype) ...)))
e9dbe4b7
AW
53 (trampoline pname ...))))))))
54
7ec693ed 55(define-syntax define-foreign-procedure
bb894c9d 56 (syntax-rules (->)
f53f928c
AW
57 ((define-foreign-procedure (name (pname ptype) ... -> type)
58 docstring)
59 (define name
60 (letrec ((trampoline
61 (foreign-trampoline trampoline
62 name (pname ptype) ... -> type))
63 (name (lambda (pname ...)
64 docstring
93f72ad8
AW
65 (let ((pname (ptype #:unwrap pname))
66 ...)
67 (type #:wrap (trampoline pname ...))))))
f53f928c
AW
68 name)))))
69
70(define-syntax define-foreign-procedures
71 (syntax-rules ()
72 ((define-foreign-procedures ((name prototype ...) ...)
bb894c9d
AW
73 docstring)
74 (begin
f53f928c
AW
75 (define-foreign-procedure (name prototype ...)
76 docstring)
bb894c9d 77 ...))))
93f72ad8
AW
78
79(define-syntax define-foreign-type
80 (syntax-rules ()
81 ((_ name ffi-type unwrap wrap)
82 (define-syntax name
83 (syntax-rules ()
84 ((_) ffi-type)
85 ((_ #:wrap x) (wrap x))
86 ((_ #:unwrap x) (unwrap x)))))))
87
88(define-syntax define-simple-foreign-type
89 (syntax-rules ()
90 ((_ name ffi-type)
91 ;; We could dispatch through to define-foreign-type via:
92 ;;
93 ;; (define-foreign-type name
94 ;; ffi-type
95 ;; (lambda (x) x)
96 ;; (lambda (x) x))
97 ;;
98 ;; However the resulting wrap expression:
99 ;;
100 ;; ((lambda (x) x) (trampoline arg ...))
101 ;;
102 ;; would not be in tail position, as the optimizer doesn't know
103 ;; that the foreign function just returns one value. This hack
104 ;; just passes the wrapped expression through, allowing it to be in
105 ;; tail position.
106 (define-syntax name
107 (syntax-rules ()
108 ((_) ffi-type)
109 ((_ #:wrap x) x)
110 ((_ #:unwrap x) x))))))