Add `struct-ref' and `struct-set' VM opcodes.
[bpt/guile.git] / module / language / tree-il / primitives.scm
1 ;;; open-coding primitive procedures
2
3 ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4
5 ;;;; This library is free software; you can redistribute it and/or
6 ;;;; modify it under the terms of the GNU Lesser General Public
7 ;;;; License as published by the Free Software Foundation; either
8 ;;;; version 3 of the License, or (at your option) any later version.
9 ;;;;
10 ;;;; This library is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ;;;; Lesser General Public License for more details.
14 ;;;;
15 ;;;; You should have received a copy of the GNU Lesser General Public
16 ;;;; License along with this library; if not, write to the Free Software
17 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 ;;; Code:
20
21 (define-module (language tree-il primitives)
22 #:use-module (system base pmatch)
23 #:use-module (rnrs bytevector)
24 #:use-module (system base syntax)
25 #:use-module (language tree-il)
26 #:use-module (srfi srfi-4)
27 #:use-module (srfi srfi-16)
28 #:export (resolve-primitives! add-interesting-primitive!
29 expand-primitives! effect-free-primitive?))
30
31 (define *interesting-primitive-names*
32 '(apply @apply
33 call-with-values @call-with-values
34 call-with-current-continuation @call-with-current-continuation
35 call/cc
36 values
37 eq? eqv? equal?
38 memq memv
39 = < > <= >= zero?
40 + * - / 1- 1+ quotient remainder modulo
41 ash logand logior logxor
42 not
43 pair? null? list? acons cons cons*
44
45 list vector
46
47 car cdr
48 set-car! set-cdr!
49
50 caar cadr cdar cddr
51
52 caaar caadr cadar caddr cdaar cdadr cddar cdddr
53
54 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
55 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
56
57 vector-ref vector-set!
58 variable-ref variable-set!
59 ;; args of variable-set are switched; it needs special help
60
61 struct? struct-vtable make-struct struct-ref struct-set!
62
63 bytevector-u8-ref bytevector-u8-set!
64 bytevector-s8-ref bytevector-s8-set!
65 u8vector-ref u8vector-set! s8vector-ref s8vector-set!
66
67 bytevector-u16-ref bytevector-u16-set!
68 bytevector-u16-native-ref bytevector-u16-native-set!
69 bytevector-s16-ref bytevector-s16-set!
70 bytevector-s16-native-ref bytevector-s16-native-set!
71 u16vector-ref u16vector-set! s16vector-ref s16vector-set!
72
73 bytevector-u32-ref bytevector-u32-set!
74 bytevector-u32-native-ref bytevector-u32-native-set!
75 bytevector-s32-ref bytevector-s32-set!
76 bytevector-s32-native-ref bytevector-s32-native-set!
77 u32vector-ref u32vector-set! s32vector-ref s32vector-set!
78
79 bytevector-u64-ref bytevector-u64-set!
80 bytevector-u64-native-ref bytevector-u64-native-set!
81 bytevector-s64-ref bytevector-s64-set!
82 bytevector-s64-native-ref bytevector-s64-native-set!
83 u64vector-ref u64vector-set! s64vector-ref s64vector-set!
84
85 bytevector-ieee-single-ref bytevector-ieee-single-set!
86 bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
87 bytevector-ieee-double-ref bytevector-ieee-double-set!
88 bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!
89 f32vector-ref f32vector-set! f64vector-ref f64vector-set!))
90
91 (define (add-interesting-primitive! name)
92 (hashq-set! *interesting-primitive-vars*
93 (or (module-variable (current-module) name)
94 (error "unbound interesting primitive" name))
95 name))
96
97 (define *interesting-primitive-vars* (make-hash-table))
98
99 (for-each add-interesting-primitive! *interesting-primitive-names*)
100
101 (define *effect-free-primitives*
102 '(values
103 eq? eqv? equal?
104 = < > <= >= zero?
105 + * - / 1- 1+ quotient remainder modulo
106 not
107 pair? null? list? acons cons cons*
108 list vector
109 car cdr
110 caar cadr cdar cddr
111 caaar caadr cadar caddr cdaar cdadr cddar cdddr
112 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
113 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
114 vector-ref
115 struct? struct-vtable make-struct struct-ref
116 bytevector-u8-ref bytevector-s8-ref
117 bytevector-u16-ref bytevector-u16-native-ref
118 bytevector-s16-ref bytevector-s16-native-ref
119 bytevector-u32-ref bytevector-u32-native-ref
120 bytevector-s32-ref bytevector-s32-native-ref
121 bytevector-u64-ref bytevector-u64-native-ref
122 bytevector-s64-ref bytevector-s64-native-ref
123 bytevector-ieee-single-ref bytevector-ieee-single-native-ref
124 bytevector-ieee-double-ref bytevector-ieee-double-native-ref))
125
126
127 (define *effect-free-primitive-table* (make-hash-table))
128
129 (for-each (lambda (x) (hashq-set! *effect-free-primitive-table* x #t))
130 *effect-free-primitives*)
131
132 (define (effect-free-primitive? prim)
133 (hashq-ref *effect-free-primitive-table* prim))
134
135 (define (resolve-primitives! x mod)
136 (post-order!
137 (lambda (x)
138 (record-case x
139 ((<toplevel-ref> src name)
140 (and=> (hashq-ref *interesting-primitive-vars*
141 (module-variable mod name))
142 (lambda (name) (make-primitive-ref src name))))
143 ((<module-ref> src mod name public?)
144 ;; for the moment, we're disabling primitive resolution for
145 ;; public refs because resolve-interface can raise errors.
146 (let ((m (and (not public?) (resolve-module mod))))
147 (and m
148 (and=> (hashq-ref *interesting-primitive-vars*
149 (module-variable m name))
150 (lambda (name) (make-primitive-ref src name))))))
151 (else #f)))
152 x))
153
154 \f
155
156 (define *primitive-expand-table* (make-hash-table))
157
158 (define (expand-primitives! x)
159 (pre-order!
160 (lambda (x)
161 (record-case x
162 ((<application> src proc args)
163 (and (primitive-ref? proc)
164 (let ((expand (hashq-ref *primitive-expand-table*
165 (primitive-ref-name proc))))
166 (and expand (apply expand src args)))))
167 (else #f)))
168 x))
169
170 ;;; I actually did spend about 10 minutes trying to redo this with
171 ;;; syntax-rules. Patches appreciated.
172 ;;;
173 (define-macro (define-primitive-expander sym . clauses)
174 (define (inline-args args)
175 (let lp ((in args) (out '()))
176 (cond ((null? in) `(list ,@(reverse out)))
177 ((symbol? in) `(cons* ,@(reverse out) ,in))
178 ((pair? (car in))
179 (lp (cdr in)
180 (cons `(make-application src (make-primitive-ref src ',(caar in))
181 ,(inline-args (cdar in)))
182 out)))
183 ((symbol? (car in))
184 ;; assume it's locally bound
185 (lp (cdr in) (cons (car in) out)))
186 ((number? (car in))
187 (lp (cdr in) (cons `(make-const src ,(car in)) out)))
188 (else
189 (error "what what" (car in))))))
190 (define (consequent exp)
191 (cond
192 ((pair? exp)
193 (pmatch exp
194 ((if ,test ,then ,else)
195 `(if ,test
196 ,(consequent then)
197 ,(consequent else)))
198 (else
199 `(make-application src (make-primitive-ref src ',(car exp))
200 ,(inline-args (cdr exp))))))
201 ((symbol? exp)
202 ;; assume locally bound
203 exp)
204 ((number? exp)
205 `(make-const src ,exp))
206 (else (error "bad consequent yall" exp))))
207 `(hashq-set! *primitive-expand-table*
208 ',sym
209 (case-lambda
210 ,@(let lp ((in clauses) (out '()))
211 (if (null? in)
212 (reverse (cons '(else #f) out))
213 (lp (cddr in)
214 (cons `((src . ,(car in))
215 ,(consequent (cadr in))) out)))))))
216
217 (define-primitive-expander zero? (x)
218 (= x 0))
219
220 (define-primitive-expander +
221 () 0
222 (x) x
223 (x y) (if (and (const? y)
224 (let ((y (const-exp y)))
225 (and (number? y) (exact? y) (= y 1))))
226 (1+ x)
227 (if (and (const? y)
228 (let ((y (const-exp y)))
229 (and (number? y) (exact? y) (= y -1))))
230 (1- x)
231 (if (and (const? x)
232 (let ((x (const-exp x)))
233 (and (number? x) (exact? x) (= x 1))))
234 (1+ y)
235 (+ x y))))
236 (x y z . rest) (+ x (+ y z . rest)))
237
238 (define-primitive-expander *
239 () 1
240 (x) x
241 (x y z . rest) (* x (* y z . rest)))
242
243 (define-primitive-expander -
244 (x) (- 0 x)
245 (x y) (if (and (const? y)
246 (let ((y (const-exp y)))
247 (and (number? y) (exact? y) (= y 1))))
248 (1- x)
249 (- x y))
250 (x y z . rest) (- x (+ y z . rest)))
251
252 (define-primitive-expander /
253 (x) (/ 1 x)
254 (x y z . rest) (/ x (* y z . rest)))
255
256 (define-primitive-expander caar (x) (car (car x)))
257 (define-primitive-expander cadr (x) (car (cdr x)))
258 (define-primitive-expander cdar (x) (cdr (car x)))
259 (define-primitive-expander cddr (x) (cdr (cdr x)))
260 (define-primitive-expander caaar (x) (car (car (car x))))
261 (define-primitive-expander caadr (x) (car (car (cdr x))))
262 (define-primitive-expander cadar (x) (car (cdr (car x))))
263 (define-primitive-expander caddr (x) (car (cdr (cdr x))))
264 (define-primitive-expander cdaar (x) (cdr (car (car x))))
265 (define-primitive-expander cdadr (x) (cdr (car (cdr x))))
266 (define-primitive-expander cddar (x) (cdr (cdr (car x))))
267 (define-primitive-expander cdddr (x) (cdr (cdr (cdr x))))
268 (define-primitive-expander caaaar (x) (car (car (car (car x)))))
269 (define-primitive-expander caaadr (x) (car (car (car (cdr x)))))
270 (define-primitive-expander caadar (x) (car (car (cdr (car x)))))
271 (define-primitive-expander caaddr (x) (car (car (cdr (cdr x)))))
272 (define-primitive-expander cadaar (x) (car (cdr (car (car x)))))
273 (define-primitive-expander cadadr (x) (car (cdr (car (cdr x)))))
274 (define-primitive-expander caddar (x) (car (cdr (cdr (car x)))))
275 (define-primitive-expander cadddr (x) (car (cdr (cdr (cdr x)))))
276 (define-primitive-expander cdaaar (x) (cdr (car (car (car x)))))
277 (define-primitive-expander cdaadr (x) (cdr (car (car (cdr x)))))
278 (define-primitive-expander cdadar (x) (cdr (car (cdr (car x)))))
279 (define-primitive-expander cdaddr (x) (cdr (car (cdr (cdr x)))))
280 (define-primitive-expander cddaar (x) (cdr (cdr (car (car x)))))
281 (define-primitive-expander cddadr (x) (cdr (cdr (car (cdr x)))))
282 (define-primitive-expander cdddar (x) (cdr (cdr (cdr (car x)))))
283 (define-primitive-expander cddddr (x) (cdr (cdr (cdr (cdr x)))))
284
285 (define-primitive-expander cons*
286 (x) x
287 (x y) (cons x y)
288 (x y . rest) (cons x (cons* y . rest)))
289
290 (define-primitive-expander acons (x y z)
291 (cons (cons x y) z))
292
293 (define-primitive-expander apply (f a0 . args)
294 (@apply f a0 . args))
295
296 (define-primitive-expander call-with-values (producer consumer)
297 (@call-with-values producer consumer))
298
299 (define-primitive-expander call-with-current-continuation (proc)
300 (@call-with-current-continuation proc))
301
302 (define-primitive-expander call/cc (proc)
303 (@call-with-current-continuation proc))
304
305 (define-primitive-expander values (x) x)
306
307 ;; swap args
308 (define-primitive-expander variable-set! (var val)
309 (variable-set val var))
310
311 (define-primitive-expander u8vector-ref (vec i)
312 (bytevector-u8-ref vec i))
313 (define-primitive-expander u8vector-set! (vec i x)
314 (bytevector-u8-set! vec i x))
315 (define-primitive-expander s8vector-ref (vec i)
316 (bytevector-s8-ref vec i))
317 (define-primitive-expander s8vector-set! (vec i x)
318 (bytevector-s8-set! vec i x))
319
320 (define-primitive-expander u16vector-ref (vec i)
321 (bytevector-u16-native-ref vec (* i 2)))
322 (define-primitive-expander u16vector-set! (vec i x)
323 (bytevector-u16-native-set! vec (* i 2) x))
324 (define-primitive-expander s16vector-ref (vec i)
325 (bytevector-s16-native-ref vec (* i 2)))
326 (define-primitive-expander s16vector-set! (vec i x)
327 (bytevector-s16-native-set! vec (* i 2) x))
328
329 (define-primitive-expander u32vector-ref (vec i)
330 (bytevector-u32-native-ref vec (* i 4)))
331 (define-primitive-expander u32vector-set! (vec i x)
332 (bytevector-u32-native-set! vec (* i 4) x))
333 (define-primitive-expander s32vector-ref (vec i)
334 (bytevector-s32-native-ref vec (* i 4)))
335 (define-primitive-expander s32vector-set! (vec i x)
336 (bytevector-s32-native-set! vec (* i 4) x))
337
338 (define-primitive-expander u64vector-ref (vec i)
339 (bytevector-u64-native-ref vec (* i 8)))
340 (define-primitive-expander u64vector-set! (vec i x)
341 (bytevector-u64-native-set! vec (* i 8) x))
342 (define-primitive-expander s64vector-ref (vec i)
343 (bytevector-s64-native-ref vec (* i 8)))
344 (define-primitive-expander s64vector-set! (vec i x)
345 (bytevector-s64-native-set! vec (* i 8) x))
346
347 (define-primitive-expander f32vector-ref (vec i)
348 (bytevector-ieee-single-native-ref vec (* i 4)))
349 (define-primitive-expander f32vector-set! (vec i x)
350 (bytevector-ieee-single-native-set! vec (* i 4) x))
351 (define-primitive-expander f32vector-ref (vec i)
352 (bytevector-ieee-single-native-ref vec (* i 4)))
353 (define-primitive-expander f32vector-set! (vec i x)
354 (bytevector-ieee-single-native-set! vec (* i 4) x))
355
356 (define-primitive-expander f64vector-ref (vec i)
357 (bytevector-ieee-double-native-ref vec (* i 8)))
358 (define-primitive-expander f64vector-set! (vec i x)
359 (bytevector-ieee-double-native-set! vec (* i 8) x))
360 (define-primitive-expander f64vector-ref (vec i)
361 (bytevector-ieee-double-native-ref vec (* i 8)))
362 (define-primitive-expander f64vector-set! (vec i x)
363 (bytevector-ieee-double-native-set! vec (* i 8) x))