Commit | Line | Data |
---|---|---|
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)))))) |