fix prompt disassembly bug
[bpt/guile.git] / module / language / tree-il / primitives.scm
CommitLineData
ac4d09b1 1;;; open-coding primitive procedures
cb28c085 2
6c498233 3;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
cb28c085 4
53befeb7
NJ
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
cb28c085
AW
18
19;;; Code:
20
55ae815b 21(define-module (language tree-il primitives)
7382f23e 22 #:use-module (system base pmatch)
39141c87 23 #:use-module (rnrs bytevector)
cb28c085
AW
24 #:use-module (system base syntax)
25 #:use-module (language tree-il)
6c498233 26 #:use-module (srfi srfi-4)
cb28c085 27 #:use-module (srfi srfi-16)
55ae815b 28 #:export (resolve-primitives! add-interesting-primitive!
80af1168 29 expand-primitives! effect-free-primitive?))
55ae815b
AW
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
1bf78495 36 dynamic-wind
d69531e2 37 @dynamic-wind
55ae815b
AW
38 values
39 eq? eqv? equal?
349d5c44 40 memq memv
55ae815b
AW
41 = < > <= >= zero?
42 + * - / 1- 1+ quotient remainder modulo
b10d9330 43 ash logand logior logxor
55ae815b
AW
44 not
45 pair? null? list? acons cons cons*
46
47 list vector
48
49 car cdr
50 set-car! set-cdr!
51
52 caar cadr cdar cddr
53
54 caaar caadr cadar caddr cdaar cdadr cddar cdddr
55
56 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
d6f1ce3d
AW
57 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
58
39141c87 59 vector-ref vector-set!
1d30393f 60 variable-ref variable-set!
d27a7811 61 variable-bound?
1d30393f 62 ;; args of variable-set are switched; it needs special help
39141c87 63
f5b1f76a
AW
64 fluid-ref fluid-set!
65
a752c0dc 66 struct? struct-vtable make-struct struct-ref struct-set!
bd91ecce 67
39141c87
AW
68 bytevector-u8-ref bytevector-u8-set!
69 bytevector-s8-ref bytevector-s8-set!
6c498233
AW
70 u8vector-ref u8vector-set! s8vector-ref s8vector-set!
71
39141c87
AW
72 bytevector-u16-ref bytevector-u16-set!
73 bytevector-u16-native-ref bytevector-u16-native-set!
74 bytevector-s16-ref bytevector-s16-set!
75 bytevector-s16-native-ref bytevector-s16-native-set!
6c498233 76 u16vector-ref u16vector-set! s16vector-ref s16vector-set!
39141c87
AW
77
78 bytevector-u32-ref bytevector-u32-set!
79 bytevector-u32-native-ref bytevector-u32-native-set!
80 bytevector-s32-ref bytevector-s32-set!
81 bytevector-s32-native-ref bytevector-s32-native-set!
6c498233 82 u32vector-ref u32vector-set! s32vector-ref s32vector-set!
39141c87
AW
83
84 bytevector-u64-ref bytevector-u64-set!
85 bytevector-u64-native-ref bytevector-u64-native-set!
86 bytevector-s64-ref bytevector-s64-set!
87 bytevector-s64-native-ref bytevector-s64-native-set!
6c498233 88 u64vector-ref u64vector-set! s64vector-ref s64vector-set!
39141c87
AW
89
90 bytevector-ieee-single-ref bytevector-ieee-single-set!
91 bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
92 bytevector-ieee-double-ref bytevector-ieee-double-set!
6c498233
AW
93 bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!
94 f32vector-ref f32vector-set! f64vector-ref f64vector-set!))
55ae815b
AW
95
96(define (add-interesting-primitive! name)
97 (hashq-set! *interesting-primitive-vars*
83c76550
AW
98 (or (module-variable (current-module) name)
99 (error "unbound interesting primitive" name))
39141c87 100 name))
55ae815b
AW
101
102(define *interesting-primitive-vars* (make-hash-table))
103
104(for-each add-interesting-primitive! *interesting-primitive-names*)
105
80af1168
AW
106(define *effect-free-primitives*
107 '(values
108 eq? eqv? equal?
109 = < > <= >= zero?
110 + * - / 1- 1+ quotient remainder modulo
111 not
112 pair? null? list? acons cons cons*
113 list vector
114 car cdr
115 caar cadr cdar cddr
116 caaar caadr cadar caddr cdaar cdadr cddar cdddr
117 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
118 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
119 vector-ref
a752c0dc 120 struct? struct-vtable make-struct struct-ref
80af1168
AW
121 bytevector-u8-ref bytevector-s8-ref
122 bytevector-u16-ref bytevector-u16-native-ref
123 bytevector-s16-ref bytevector-s16-native-ref
124 bytevector-u32-ref bytevector-u32-native-ref
125 bytevector-s32-ref bytevector-s32-native-ref
126 bytevector-u64-ref bytevector-u64-native-ref
127 bytevector-s64-ref bytevector-s64-native-ref
128 bytevector-ieee-single-ref bytevector-ieee-single-native-ref
129 bytevector-ieee-double-ref bytevector-ieee-double-native-ref))
130
131
132(define *effect-free-primitive-table* (make-hash-table))
133
134(for-each (lambda (x) (hashq-set! *effect-free-primitive-table* x #t))
135 *effect-free-primitives*)
136
137(define (effect-free-primitive? prim)
138 (hashq-ref *effect-free-primitive-table* prim))
139
55ae815b
AW
140(define (resolve-primitives! x mod)
141 (post-order!
142 (lambda (x)
143 (record-case x
144 ((<toplevel-ref> src name)
c0ee3245
AW
145 (and=> (hashq-ref *interesting-primitive-vars*
146 (module-variable mod name))
147 (lambda (name) (make-primitive-ref src name))))
55ae815b
AW
148 ((<module-ref> src mod name public?)
149 ;; for the moment, we're disabling primitive resolution for
150 ;; public refs because resolve-interface can raise errors.
151 (let ((m (and (not public?) (resolve-module mod))))
c0ee3245
AW
152 (and m
153 (and=> (hashq-ref *interesting-primitive-vars*
154 (module-variable m name))
155 (lambda (name) (make-primitive-ref src name))))))
55ae815b
AW
156 (else #f)))
157 x))
158
159\f
cb28c085
AW
160
161(define *primitive-expand-table* (make-hash-table))
162
163(define (expand-primitives! x)
164 (pre-order!
165 (lambda (x)
166 (record-case x
167 ((<application> src proc args)
168 (and (primitive-ref? proc)
169 (let ((expand (hashq-ref *primitive-expand-table*
170 (primitive-ref-name proc))))
171 (and expand (apply expand src args)))))
172 (else #f)))
173 x))
174
175;;; I actually did spend about 10 minutes trying to redo this with
176;;; syntax-rules. Patches appreciated.
177;;;
178(define-macro (define-primitive-expander sym . clauses)
179 (define (inline-args args)
180 (let lp ((in args) (out '()))
181 (cond ((null? in) `(list ,@(reverse out)))
182 ((symbol? in) `(cons* ,@(reverse out) ,in))
183 ((pair? (car in))
184 (lp (cdr in)
9b2a2a39
AW
185 (cons (if (eq? (caar in) 'quote)
186 `(make-const src ,@(cdar in))
187 `(make-application src (make-primitive-ref src ',(caar in))
188 ,(inline-args (cdar in))))
cb28c085
AW
189 out)))
190 ((symbol? (car in))
191 ;; assume it's locally bound
192 (lp (cdr in) (cons (car in) out)))
9b2a2a39 193 ((self-evaluating? (car in))
cb28c085
AW
194 (lp (cdr in) (cons `(make-const src ,(car in)) out)))
195 (else
196 (error "what what" (car in))))))
197 (define (consequent exp)
198 (cond
199 ((pair? exp)
7382f23e
AW
200 (pmatch exp
201 ((if ,test ,then ,else)
202 `(if ,test
203 ,(consequent then)
204 ,(consequent else)))
205 (else
206 `(make-application src (make-primitive-ref src ',(car exp))
207 ,(inline-args (cdr exp))))))
cb28c085
AW
208 ((symbol? exp)
209 ;; assume locally bound
210 exp)
211 ((number? exp)
212 `(make-const src ,exp))
213 (else (error "bad consequent yall" exp))))
214 `(hashq-set! *primitive-expand-table*
215 ',sym
216 (case-lambda
217 ,@(let lp ((in clauses) (out '()))
218 (if (null? in)
219 (reverse (cons '(else #f) out))
220 (lp (cddr in)
221 (cons `((src . ,(car in))
222 ,(consequent (cadr in))) out)))))))
223
9b29d607
AW
224(define-primitive-expander zero? (x)
225 (= x 0))
226
cb28c085
AW
227(define-primitive-expander +
228 () 0
229 (x) x
7382f23e
AW
230 (x y) (if (and (const? y)
231 (let ((y (const-exp y)))
eebff6d7 232 (and (number? y) (exact? y) (= y 1))))
7382f23e 233 (1+ x)
8753fd53 234 (if (and (const? y)
dd902692
LC
235 (let ((y (const-exp y)))
236 (and (number? y) (exact? y) (= y -1))))
8753fd53
AW
237 (1- x)
238 (if (and (const? x)
239 (let ((x (const-exp x)))
dd902692 240 (and (number? x) (exact? x) (= x 1))))
8753fd53
AW
241 (1+ y)
242 (+ x y))))
cb28c085
AW
243 (x y z . rest) (+ x (+ y z . rest)))
244
245(define-primitive-expander *
246 () 1
247 (x) x
248 (x y z . rest) (* x (* y z . rest)))
249
250(define-primitive-expander -
251 (x) (- 0 x)
7382f23e
AW
252 (x y) (if (and (const? y)
253 (let ((y (const-exp y)))
eebff6d7 254 (and (number? y) (exact? y) (= y 1))))
7382f23e
AW
255 (1- x)
256 (- x y))
cb28c085
AW
257 (x y z . rest) (- x (+ y z . rest)))
258
cb28c085
AW
259(define-primitive-expander /
260 (x) (/ 1 x)
81fd3152 261 (x y z . rest) (/ x (* y z . rest)))
cb28c085
AW
262
263(define-primitive-expander caar (x) (car (car x)))
264(define-primitive-expander cadr (x) (car (cdr x)))
265(define-primitive-expander cdar (x) (cdr (car x)))
266(define-primitive-expander cddr (x) (cdr (cdr x)))
267(define-primitive-expander caaar (x) (car (car (car x))))
268(define-primitive-expander caadr (x) (car (car (cdr x))))
269(define-primitive-expander cadar (x) (car (cdr (car x))))
270(define-primitive-expander caddr (x) (car (cdr (cdr x))))
271(define-primitive-expander cdaar (x) (cdr (car (car x))))
272(define-primitive-expander cdadr (x) (cdr (car (cdr x))))
273(define-primitive-expander cddar (x) (cdr (cdr (car x))))
274(define-primitive-expander cdddr (x) (cdr (cdr (cdr x))))
275(define-primitive-expander caaaar (x) (car (car (car (car x)))))
276(define-primitive-expander caaadr (x) (car (car (car (cdr x)))))
277(define-primitive-expander caadar (x) (car (car (cdr (car x)))))
278(define-primitive-expander caaddr (x) (car (car (cdr (cdr x)))))
279(define-primitive-expander cadaar (x) (car (cdr (car (car x)))))
280(define-primitive-expander cadadr (x) (car (cdr (car (cdr x)))))
281(define-primitive-expander caddar (x) (car (cdr (cdr (car x)))))
282(define-primitive-expander cadddr (x) (car (cdr (cdr (cdr x)))))
283(define-primitive-expander cdaaar (x) (cdr (car (car (car x)))))
284(define-primitive-expander cdaadr (x) (cdr (car (car (cdr x)))))
285(define-primitive-expander cdadar (x) (cdr (car (cdr (car x)))))
286(define-primitive-expander cdaddr (x) (cdr (car (cdr (cdr x)))))
287(define-primitive-expander cddaar (x) (cdr (cdr (car (car x)))))
288(define-primitive-expander cddadr (x) (cdr (cdr (car (cdr x)))))
289(define-primitive-expander cdddar (x) (cdr (cdr (cdr (car x)))))
290(define-primitive-expander cddddr (x) (cdr (cdr (cdr (cdr x)))))
291
292(define-primitive-expander cons*
293 (x) x
294 (x y) (cons x y)
295 (x y . rest) (cons x (cons* y . rest)))
296
dce042f1
AW
297(define-primitive-expander acons (x y z)
298 (cons (cons x y) z))
299
0e249fd3
AW
300(define-primitive-expander apply (f a0 . args)
301 (@apply f a0 . args))
dce042f1
AW
302
303(define-primitive-expander call-with-values (producer consumer)
304 (@call-with-values producer consumer))
305
306(define-primitive-expander call-with-current-continuation (proc)
307 (@call-with-current-continuation proc))
308
0f423f20
AW
309(define-primitive-expander call/cc (proc)
310 (@call-with-current-continuation proc))
311
dce042f1 312(define-primitive-expander values (x) x)
1d30393f
AW
313
314;; swap args
315(define-primitive-expander variable-set! (var val)
316 (variable-set val var))
6c498233
AW
317
318(define-primitive-expander u8vector-ref (vec i)
319 (bytevector-u8-ref vec i))
320(define-primitive-expander u8vector-set! (vec i x)
321 (bytevector-u8-set! vec i x))
322(define-primitive-expander s8vector-ref (vec i)
323 (bytevector-s8-ref vec i))
324(define-primitive-expander s8vector-set! (vec i x)
325 (bytevector-s8-set! vec i x))
326
327(define-primitive-expander u16vector-ref (vec i)
328 (bytevector-u16-native-ref vec (* i 2)))
329(define-primitive-expander u16vector-set! (vec i x)
330 (bytevector-u16-native-set! vec (* i 2) x))
331(define-primitive-expander s16vector-ref (vec i)
332 (bytevector-s16-native-ref vec (* i 2)))
333(define-primitive-expander s16vector-set! (vec i x)
334 (bytevector-s16-native-set! vec (* i 2) x))
335
336(define-primitive-expander u32vector-ref (vec i)
337 (bytevector-u32-native-ref vec (* i 4)))
338(define-primitive-expander u32vector-set! (vec i x)
339 (bytevector-u32-native-set! vec (* i 4) x))
340(define-primitive-expander s32vector-ref (vec i)
341 (bytevector-s32-native-ref vec (* i 4)))
342(define-primitive-expander s32vector-set! (vec i x)
343 (bytevector-s32-native-set! vec (* i 4) x))
344
345(define-primitive-expander u64vector-ref (vec i)
346 (bytevector-u64-native-ref vec (* i 8)))
347(define-primitive-expander u64vector-set! (vec i x)
348 (bytevector-u64-native-set! vec (* i 8) x))
349(define-primitive-expander s64vector-ref (vec i)
350 (bytevector-s64-native-ref vec (* i 8)))
351(define-primitive-expander s64vector-set! (vec i x)
352 (bytevector-s64-native-set! vec (* i 8) x))
353
354(define-primitive-expander f32vector-ref (vec i)
355 (bytevector-ieee-single-native-ref vec (* i 4)))
356(define-primitive-expander f32vector-set! (vec i x)
357 (bytevector-ieee-single-native-set! vec (* i 4) x))
358(define-primitive-expander f32vector-ref (vec i)
359 (bytevector-ieee-single-native-ref vec (* i 4)))
360(define-primitive-expander f32vector-set! (vec i x)
361 (bytevector-ieee-single-native-set! vec (* i 4) x))
362
363(define-primitive-expander f64vector-ref (vec i)
364 (bytevector-ieee-double-native-ref vec (* i 8)))
365(define-primitive-expander f64vector-set! (vec i x)
366 (bytevector-ieee-double-native-set! vec (* i 8) x))
367(define-primitive-expander f64vector-ref (vec i)
368 (bytevector-ieee-double-native-ref vec (* i 8)))
369(define-primitive-expander f64vector-set! (vec i x)
370 (bytevector-ieee-double-native-set! vec (* i 8) x))
1bf78495
AW
371
372(hashq-set! *primitive-expand-table*
373 'dynamic-wind
374 (case-lambda
375 ((src pre thunk post)
376 ;; Here we will make concessions to the fact that our inliner is
377 ;; lame, and add a hack.
378 (cond
379 ((lambda? thunk)
380 (let ((PRE (gensym " pre"))
381 (POST (gensym " post")))
382 (make-let
383 src
384 '(pre post)
385 (list PRE POST)
386 (list pre post)
8da6ab34 387 (make-dynwind
1bf78495
AW
388 src
389 (make-lexical-ref #f 'pre PRE)
390 (make-application #f thunk '())
391 (make-lexical-ref #f 'post POST)))))
392 (else
393 (let ((PRE (gensym " pre"))
394 (THUNK (gensym " thunk"))
395 (POST (gensym " post")))
396 (make-let
397 src
398 '(pre thunk post)
399 (list PRE THUNK POST)
400 (list pre thunk post)
8da6ab34 401 (make-dynwind
1bf78495
AW
402 src
403 (make-lexical-ref #f 'pre PRE)
404 (make-application #f (make-lexical-ref #f 'thunk THUNK) '())
405 (make-lexical-ref #f 'post POST)))))))
406 (else #f)))
9b2a2a39 407
d69531e2
AW
408(hashq-set! *primitive-expand-table*
409 '@dynamic-wind
410 (case-lambda
411 ((src pre expr post)
412 (let ((PRE (gensym " pre"))
413 (POST (gensym " post")))
414 (make-let
415 src
416 '(pre post)
417 (list PRE POST)
418 (list pre post)
8da6ab34 419 (make-dynwind
d69531e2
AW
420 src
421 (make-lexical-ref #f 'pre PRE)
422 expr
423 (make-lexical-ref #f 'post POST)))))))
424
f5b1f76a
AW
425(hashq-set! *primitive-expand-table*
426 'fluid-ref
427 (case-lambda
428 ((src fluid) (make-dynref src fluid))
429 (else #f)))
430
431(hashq-set! *primitive-expand-table*
432 'fluid-set!
433 (case-lambda
434 ((src fluid exp) (make-dynset src fluid exp))
435 (else #f)))
436
9b2a2a39
AW
437(hashq-set! *primitive-expand-table*
438 '@prompt
439 (case-lambda
ea6b18e8
AW
440 ((src tag exp handler)
441 (let ((args-sym (gensym)))
442 (make-prompt
443 src tag exp
444 ;; If handler itself is a lambda, the inliner can do some
445 ;; trickery here.
446 (make-lambda-case
447 (tree-il-src handler) '() #f 'args #f '() (list args-sym)
448 (make-application #f (make-primitive-ref #f 'apply)
449 (list handler
450 (make-lexical-ref #f 'args args-sym)))
451 #f))))
9b2a2a39
AW
452 (else #f)))
453
454(hashq-set! *primitive-expand-table*
455 'control
456 (case-lambda
457 ((src tag . args)
6e84cb95 458 (make-abort src tag args))
9b2a2a39
AW
459 (else #f)))
460(hashq-set! *primitive-expand-table*
461 '@control
462 (case-lambda
6e84cb95
AW
463 ((src tag . args)
464 (make-abort src tag args))
9b2a2a39 465 (else #f)))