Optimizer support for logtest and logbit?
[bpt/guile.git] / module / language / tree-il / primitives.scm
CommitLineData
ac4d09b1 1;;; open-coding primitive procedures
cb28c085 2
ae7f13be 3;; Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 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)
71673fba 23 #:use-module (ice-9 match)
07d22c02 24 #:use-module (rnrs bytevectors)
cb28c085
AW
25 #:use-module (system base syntax)
26 #:use-module (language tree-il)
6c498233 27 #:use-module (srfi srfi-4)
cb28c085 28 #:use-module (srfi srfi-16)
403d78f9 29 #:export (resolve-primitives add-interesting-primitive!
25450a0d 30 expand-primitives
11671bba 31 effect-free-primitive? effect+exception-free-primitive?
863dd873 32 constructor-primitive?
c46e0a8a
AW
33 singly-valued-primitive? equality-primitive?
34 bailout-primitive?
5deea34d 35 negate-primitive))
55ae815b 36
5deea34d
AW
37;; When adding to this, be sure to update *multiply-valued-primitives*
38;; if appropriate.
55ae815b 39(define *interesting-primitive-names*
39caffe7 40 '(apply
0fcc39a0 41 call-with-values
bc056057 42 call-with-current-continuation
55ae815b 43 call/cc
1bf78495 44 dynamic-wind
55ae815b
AW
45 values
46 eq? eqv? equal?
349d5c44 47 memq memv
ca5e0414 48 = < > <= >= zero? positive? negative?
55ae815b 49 + * - / 1- 1+ quotient remainder modulo
8006d2d6 50 ash logand logior logxor lognot logtest logbit?
9b3c4ced 51 sqrt abs
55ae815b 52 not
c46e0a8a 53 pair? null? list? symbol? vector? string? struct? number? char? nil?
5deea34d 54
bb97e4ab
AW
55 procedure? thunk?
56
5deea34d
AW
57 complex? real? rational? inf? nan? integer? exact? inexact? even? odd?
58
59 char<? char<=? char>=? char>?
60
2874f660
AW
61 integer->char char->integer number->string string->number
62
9be8a338 63 acons cons cons*
55ae815b
AW
64
65 list vector
66
67 car cdr
68 set-car! set-cdr!
69
70 caar cadr cdar cddr
71
72 caaar caadr cadar caddr cdaar cdadr cddar cdddr
73
74 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
d6f1ce3d
AW
75 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
76
91fc226e
AW
77 length
78
607fe5a6 79 make-vector vector-length vector-ref vector-set!
d023ae86 80 variable? variable-ref variable-set!
d27a7811 81 variable-bound?
39141c87 82
3e248c70 83 current-module define!
d422f316 84
c32b7c4c 85 fluid-ref fluid-set! with-fluid*
f5b1f76a 86
1773bc7d 87 call-with-prompt
38504994 88 abort-to-prompt* abort-to-prompt
38030bdf 89 make-prompt-tag
747022e4 90
5deea34d
AW
91 throw error scm-error
92
9be8a338
AW
93 string-length string-ref string-set!
94
4c906ad5 95 allocate-struct struct-vtable make-struct struct-ref struct-set!
bd91ecce 96
a694809e
AW
97 bytevector-length
98
39141c87
AW
99 bytevector-u8-ref bytevector-u8-set!
100 bytevector-s8-ref bytevector-s8-set!
6c498233
AW
101 u8vector-ref u8vector-set! s8vector-ref s8vector-set!
102
39141c87
AW
103 bytevector-u16-ref bytevector-u16-set!
104 bytevector-u16-native-ref bytevector-u16-native-set!
105 bytevector-s16-ref bytevector-s16-set!
106 bytevector-s16-native-ref bytevector-s16-native-set!
6c498233 107 u16vector-ref u16vector-set! s16vector-ref s16vector-set!
39141c87
AW
108
109 bytevector-u32-ref bytevector-u32-set!
110 bytevector-u32-native-ref bytevector-u32-native-set!
111 bytevector-s32-ref bytevector-s32-set!
112 bytevector-s32-native-ref bytevector-s32-native-set!
6c498233 113 u32vector-ref u32vector-set! s32vector-ref s32vector-set!
39141c87
AW
114
115 bytevector-u64-ref bytevector-u64-set!
116 bytevector-u64-native-ref bytevector-u64-native-set!
117 bytevector-s64-ref bytevector-s64-set!
118 bytevector-s64-native-ref bytevector-s64-native-set!
6c498233 119 u64vector-ref u64vector-set! s64vector-ref s64vector-set!
39141c87
AW
120
121 bytevector-ieee-single-ref bytevector-ieee-single-set!
122 bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
123 bytevector-ieee-double-ref bytevector-ieee-double-set!
6c498233
AW
124 bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!
125 f32vector-ref f32vector-set! f64vector-ref f64vector-set!))
55ae815b
AW
126
127(define (add-interesting-primitive! name)
128 (hashq-set! *interesting-primitive-vars*
83c76550
AW
129 (or (module-variable (current-module) name)
130 (error "unbound interesting primitive" name))
39141c87 131 name))
55ae815b
AW
132
133(define *interesting-primitive-vars* (make-hash-table))
134
135(for-each add-interesting-primitive! *interesting-primitive-names*)
136
11671bba
LC
137(define *primitive-constructors*
138 ;; Primitives that return a fresh object.
4c906ad5
AW
139 '(acons cons cons* list vector make-vector
140 allocate-struct make-struct make-struct/no-tail
f26c3a93
AW
141 make-prompt-tag))
142
143(define *primitive-accessors*
144 ;; Primitives that are pure, but whose result depends on the mutable
145 ;; memory pointed to by their operands.
863dd873
AW
146 ;;
147 ;; Note: if you add an accessor here, be sure to add a corresponding
148 ;; case in (language tree-il effects)!
f26c3a93
AW
149 '(vector-ref
150 car cdr
151 memq memv
5deea34d 152 struct-ref
9be8a338 153 string-ref
f26c3a93
AW
154 bytevector-u8-ref bytevector-s8-ref
155 bytevector-u16-ref bytevector-u16-native-ref
156 bytevector-s16-ref bytevector-s16-native-ref
157 bytevector-u32-ref bytevector-u32-native-ref
158 bytevector-s32-ref bytevector-s32-native-ref
159 bytevector-u64-ref bytevector-u64-native-ref
160 bytevector-s64-ref bytevector-s64-native-ref
161 bytevector-ieee-single-ref bytevector-ieee-single-native-ref
162 bytevector-ieee-double-ref bytevector-ieee-double-native-ref))
11671bba 163
80af1168 164(define *effect-free-primitives*
11671bba 165 `(values
80af1168 166 eq? eqv? equal?
ca5e0414 167 = < > <= >= zero? positive? negative?
8006d2d6 168 ash logand logior logxor lognot logtest logbit?
9b3c4ced 169 + * - / 1- 1+ sqrt abs quotient remainder modulo
80af1168 170 not
d023ae86
AW
171 pair? null? nil? list?
172 symbol? variable? vector? struct? string? number? char?
5deea34d
AW
173 complex? real? rational? inf? nan? integer? exact? inexact? even? odd?
174 char<? char<=? char>=? char>?
2874f660 175 integer->char char->integer number->string string->number
5deea34d 176 struct-vtable
a694809e 177 length string-length vector-length bytevector-length
25450a0d 178 ;; These all should get expanded out by expand-primitives.
80af1168
AW
179 caar cadr cdar cddr
180 caaar caadr cadar caddr cdaar cdadr cddar cdddr
181 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
182 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
f26c3a93
AW
183 ,@*primitive-constructors*
184 ,@*primitive-accessors*))
80af1168 185
4ee781a6
AW
186;; Like *effect-free-primitives* above, but further restricted in that they
187;; cannot raise exceptions.
188(define *effect+exception-free-primitives*
189 '(values
190 eq? eqv? equal?
191 not
d023ae86
AW
192 pair? null? nil? list?
193 symbol? variable? vector? struct? string? number? char?
bb97e4ab 194 procedure? thunk?
f26c3a93 195 acons cons cons* list vector))
80af1168 196
5deea34d
AW
197;; Primitives that don't always return one value.
198(define *multiply-valued-primitives*
39caffe7 199 '(apply
0fcc39a0 200 call-with-values
bc056057 201 call-with-current-continuation
5deea34d
AW
202 call/cc
203 dynamic-wind
5deea34d 204 values
1773bc7d 205 call-with-prompt
38504994 206 @abort abort-to-prompt))
5deea34d
AW
207
208;; Procedures that cause a nonlocal, non-resumable abort.
209(define *bailout-primitives*
210 '(throw error scm-error))
211
212;; Negatable predicates.
213(define *negatable-primitives*
214 '((even? . odd?)
215 (exact? . inexact?)
73b98028 216 ;; (< <= > >=) are not negatable because of NaNs.
5deea34d
AW
217 (char<? . char>=?)
218 (char>? . char<=?)))
03026d0f 219
3c65e3fd
NL
220(define *equality-primitives*
221 '(eq? eqv? equal?))
222
80af1168 223(define *effect-free-primitive-table* (make-hash-table))
4ee781a6 224(define *effect+exceptions-free-primitive-table* (make-hash-table))
3c65e3fd 225(define *equality-primitive-table* (make-hash-table))
5deea34d
AW
226(define *multiply-valued-primitive-table* (make-hash-table))
227(define *bailout-primitive-table* (make-hash-table))
228(define *negatable-primitive-table* (make-hash-table))
80af1168 229
4ee781a6
AW
230(for-each (lambda (x)
231 (hashq-set! *effect-free-primitive-table* x #t))
80af1168 232 *effect-free-primitives*)
4ee781a6
AW
233(for-each (lambda (x)
234 (hashq-set! *effect+exceptions-free-primitive-table* x #t))
235 *effect+exception-free-primitives*)
3c65e3fd
NL
236(for-each (lambda (x)
237 (hashq-set! *equality-primitive-table* x #t))
238 *equality-primitives*)
03026d0f 239(for-each (lambda (x)
5deea34d
AW
240 (hashq-set! *multiply-valued-primitive-table* x #t))
241 *multiply-valued-primitives*)
242(for-each (lambda (x)
243 (hashq-set! *bailout-primitive-table* x #t))
244 *bailout-primitives*)
245(for-each (lambda (x)
246 (hashq-set! *negatable-primitive-table* (car x) (cdr x))
247 (hashq-set! *negatable-primitive-table* (cdr x) (car x)))
248 *negatable-primitives*)
80af1168 249
11671bba
LC
250(define (constructor-primitive? prim)
251 (memq prim *primitive-constructors*))
80af1168
AW
252(define (effect-free-primitive? prim)
253 (hashq-ref *effect-free-primitive-table* prim))
4ee781a6
AW
254(define (effect+exception-free-primitive? prim)
255 (hashq-ref *effect+exceptions-free-primitive-table* prim))
3c65e3fd
NL
256(define (equality-primitive? prim)
257 (hashq-ref *equality-primitive-table* prim))
03026d0f 258(define (singly-valued-primitive? prim)
5deea34d
AW
259 (not (hashq-ref *multiply-valued-primitive-table* prim)))
260(define (bailout-primitive? prim)
261 (hashq-ref *bailout-primitive-table* prim))
262(define (negate-primitive prim)
263 (hashq-ref *negatable-primitive-table* prim))
80af1168 264
403d78f9 265(define (resolve-primitives x mod)
14b20818
AW
266 (define local-definitions
267 (make-hash-table))
268
33e9a90d
AW
269 ;; Assume that any definitions with primitive names in the root module
270 ;; have the same semantics as the primitives.
271 (unless (eq? mod the-root-module)
272 (let collect-local-definitions ((x x))
273 (record-case x
274 ((<toplevel-define> name)
275 (hashq-set! local-definitions name #t))
276 ((<seq> head tail)
277 (collect-local-definitions head)
278 (collect-local-definitions tail))
279 (else #f))))
14b20818 280
403d78f9 281 (post-order
55ae815b 282 (lambda (x)
403d78f9
AW
283 (or
284 (record-case x
285 ((<toplevel-ref> src name)
286 (and=> (and (not (hashq-ref local-definitions name))
287 (hashq-ref *interesting-primitive-vars*
288 (module-variable mod name)))
289 (lambda (name) (make-primitive-ref src name))))
290 ((<module-ref> src mod name public?)
291 ;; for the moment, we're disabling primitive resolution for
292 ;; public refs because resolve-interface can raise errors.
293 (and=> (and=> (resolve-module mod)
294 (if public?
295 module-public-interface
296 identity))
297 (lambda (m)
298 (and=> (hashq-ref *interesting-primitive-vars*
299 (module-variable m name))
300 (lambda (name)
301 (make-primitive-ref src name))))))
302 ((<call> src proc args)
303 (and (primitive-ref? proc)
304 (make-primcall src (primitive-ref-name proc) args)))
305 (else #f))
306 x))
55ae815b
AW
307 x))
308
309\f
cb28c085
AW
310
311(define *primitive-expand-table* (make-hash-table))
312
25450a0d
AW
313(define (expand-primitives x)
314 (pre-order
cb28c085
AW
315 (lambda (x)
316 (record-case x
a881a4ae
AW
317 ((<primcall> src name args)
318 (let ((expand (hashq-ref *primitive-expand-table* name)))
25450a0d
AW
319 (or (and expand (apply expand src args))
320 x)))
321 (else x)))
cb28c085
AW
322 x))
323
324;;; I actually did spend about 10 minutes trying to redo this with
325;;; syntax-rules. Patches appreciated.
326;;;
327(define-macro (define-primitive-expander sym . clauses)
328 (define (inline-args args)
329 (let lp ((in args) (out '()))
330 (cond ((null? in) `(list ,@(reverse out)))
331 ((symbol? in) `(cons* ,@(reverse out) ,in))
332 ((pair? (car in))
333 (lp (cdr in)
9b2a2a39
AW
334 (cons (if (eq? (caar in) 'quote)
335 `(make-const src ,@(cdar in))
a881a4ae
AW
336 `(make-primcall src ',(caar in)
337 ,(inline-args (cdar in))))
cb28c085
AW
338 out)))
339 ((symbol? (car in))
340 ;; assume it's locally bound
341 (lp (cdr in) (cons (car in) out)))
9b2a2a39 342 ((self-evaluating? (car in))
cb28c085
AW
343 (lp (cdr in) (cons `(make-const src ,(car in)) out)))
344 (else
345 (error "what what" (car in))))))
346 (define (consequent exp)
347 (cond
348 ((pair? exp)
7382f23e
AW
349 (pmatch exp
350 ((if ,test ,then ,else)
351 `(if ,test
352 ,(consequent then)
353 ,(consequent else)))
354 (else
a881a4ae
AW
355 `(make-primcall src ',(car exp)
356 ,(inline-args (cdr exp))))))
cb28c085
AW
357 ((symbol? exp)
358 ;; assume locally bound
359 exp)
360 ((number? exp)
361 `(make-const src ,exp))
9a974fd3
AW
362 ((not exp)
363 ;; failed match
364 #f)
cb28c085
AW
365 (else (error "bad consequent yall" exp))))
366 `(hashq-set! *primitive-expand-table*
367 ',sym
71673fba 368 (match-lambda*
cb28c085
AW
369 ,@(let lp ((in clauses) (out '()))
370 (if (null? in)
71673fba 371 (reverse (cons '(_ #f) out))
cb28c085
AW
372 (lp (cddr in)
373 (cons `((src . ,(car in))
71673fba
MW
374 ,(consequent (cadr in)))
375 out)))))))
cb28c085 376
9b29d607
AW
377(define-primitive-expander zero? (x)
378 (= x 0))
379
ca5e0414
MW
380(define-primitive-expander positive? (x)
381 (> x 0))
382
383(define-primitive-expander negative? (x)
384 (< x 0))
385
11671bba
LC
386;; FIXME: All the code that uses `const?' is redundant with `peval'.
387
cb28c085
AW
388(define-primitive-expander +
389 () 0
b88fef55 390 (x) (values x)
71673fba 391 (x y) (if (and (const? y) (eqv? (const-exp y) 1))
7382f23e 392 (1+ x)
71673fba 393 (if (and (const? y) (eqv? (const-exp y) -1))
8753fd53 394 (1- x)
71673fba 395 (if (and (const? x) (eqv? (const-exp x) 1))
8753fd53 396 (1+ y)
71673fba
MW
397 (if (and (const? x) (eqv? (const-exp x) -1))
398 (1- y)
399 (+ x y)))))
400 (x y z ... last) (+ (+ x y . z) last))
401
cb28c085
AW
402(define-primitive-expander *
403 () 1
b88fef55 404 (x) (values x)
71673fba 405 (x y z ... last) (* (* x y . z) last))
cb28c085
AW
406
407(define-primitive-expander -
408 (x) (- 0 x)
71673fba 409 (x y) (if (and (const? y) (eqv? (const-exp y) 1))
7382f23e
AW
410 (1- x)
411 (- x y))
71673fba 412 (x y z ... last) (- (- x y . z) last))
cb28c085 413
cb28c085
AW
414(define-primitive-expander /
415 (x) (/ 1 x)
71673fba 416 (x y z ... last) (/ (/ x y . z) last))
cb28c085 417
b3f25e62
AW
418(define-primitive-expander logior
419 () 0
420 (x) (logior x 0)
421 (x y) (logior x y)
71673fba 422 (x y z ... last) (logior (logior x y . z) last))
b3f25e62
AW
423
424(define-primitive-expander logand
425 () -1
426 (x) (logand x -1)
427 (x y) (logand x y)
71673fba 428 (x y z ... last) (logand (logand x y . z) last))
b3f25e62 429
cb28c085
AW
430(define-primitive-expander caar (x) (car (car x)))
431(define-primitive-expander cadr (x) (car (cdr x)))
432(define-primitive-expander cdar (x) (cdr (car x)))
433(define-primitive-expander cddr (x) (cdr (cdr x)))
434(define-primitive-expander caaar (x) (car (car (car x))))
435(define-primitive-expander caadr (x) (car (car (cdr x))))
436(define-primitive-expander cadar (x) (car (cdr (car x))))
437(define-primitive-expander caddr (x) (car (cdr (cdr x))))
438(define-primitive-expander cdaar (x) (cdr (car (car x))))
439(define-primitive-expander cdadr (x) (cdr (car (cdr x))))
440(define-primitive-expander cddar (x) (cdr (cdr (car x))))
441(define-primitive-expander cdddr (x) (cdr (cdr (cdr x))))
442(define-primitive-expander caaaar (x) (car (car (car (car x)))))
443(define-primitive-expander caaadr (x) (car (car (car (cdr x)))))
444(define-primitive-expander caadar (x) (car (car (cdr (car x)))))
445(define-primitive-expander caaddr (x) (car (car (cdr (cdr x)))))
446(define-primitive-expander cadaar (x) (car (cdr (car (car x)))))
447(define-primitive-expander cadadr (x) (car (cdr (car (cdr x)))))
448(define-primitive-expander caddar (x) (car (cdr (cdr (car x)))))
449(define-primitive-expander cadddr (x) (car (cdr (cdr (cdr x)))))
450(define-primitive-expander cdaaar (x) (cdr (car (car (car x)))))
451(define-primitive-expander cdaadr (x) (cdr (car (car (cdr x)))))
452(define-primitive-expander cdadar (x) (cdr (car (cdr (car x)))))
453(define-primitive-expander cdaddr (x) (cdr (car (cdr (cdr x)))))
454(define-primitive-expander cddaar (x) (cdr (cdr (car (car x)))))
455(define-primitive-expander cddadr (x) (cdr (cdr (car (cdr x)))))
456(define-primitive-expander cdddar (x) (cdr (cdr (cdr (car x)))))
457(define-primitive-expander cddddr (x) (cdr (cdr (cdr (cdr x)))))
458
459(define-primitive-expander cons*
b88fef55 460 (x) (values x)
cb28c085
AW
461 (x y) (cons x y)
462 (x y . rest) (cons x (cons* y . rest)))
463
dce042f1
AW
464(define-primitive-expander acons (x y z)
465 (cons (cons x y) z))
466
0f423f20 467(define-primitive-expander call/cc (proc)
bc056057 468 (call-with-current-continuation proc))
0f423f20 469
9a974fd3
AW
470(define-primitive-expander make-struct (vtable tail-size . args)
471 (if (and (const? tail-size)
472 (let ((n (const-exp tail-size)))
473 (and (number? n) (exact? n) (zero? n))))
474 (make-struct/no-tail vtable . args)
475 #f))
476
6c498233
AW
477(define-primitive-expander u8vector-ref (vec i)
478 (bytevector-u8-ref vec i))
479(define-primitive-expander u8vector-set! (vec i x)
480 (bytevector-u8-set! vec i x))
481(define-primitive-expander s8vector-ref (vec i)
482 (bytevector-s8-ref vec i))
483(define-primitive-expander s8vector-set! (vec i x)
484 (bytevector-s8-set! vec i x))
485
486(define-primitive-expander u16vector-ref (vec i)
487 (bytevector-u16-native-ref vec (* i 2)))
488(define-primitive-expander u16vector-set! (vec i x)
489 (bytevector-u16-native-set! vec (* i 2) x))
490(define-primitive-expander s16vector-ref (vec i)
491 (bytevector-s16-native-ref vec (* i 2)))
492(define-primitive-expander s16vector-set! (vec i x)
493 (bytevector-s16-native-set! vec (* i 2) x))
494
495(define-primitive-expander u32vector-ref (vec i)
496 (bytevector-u32-native-ref vec (* i 4)))
497(define-primitive-expander u32vector-set! (vec i x)
498 (bytevector-u32-native-set! vec (* i 4) x))
499(define-primitive-expander s32vector-ref (vec i)
500 (bytevector-s32-native-ref vec (* i 4)))
501(define-primitive-expander s32vector-set! (vec i x)
502 (bytevector-s32-native-set! vec (* i 4) x))
503
504(define-primitive-expander u64vector-ref (vec i)
505 (bytevector-u64-native-ref vec (* i 8)))
506(define-primitive-expander u64vector-set! (vec i x)
507 (bytevector-u64-native-set! vec (* i 8) x))
508(define-primitive-expander s64vector-ref (vec i)
509 (bytevector-s64-native-ref vec (* i 8)))
510(define-primitive-expander s64vector-set! (vec i x)
511 (bytevector-s64-native-set! vec (* i 8) x))
512
513(define-primitive-expander f32vector-ref (vec i)
514 (bytevector-ieee-single-native-ref vec (* i 4)))
515(define-primitive-expander f32vector-set! (vec i x)
516 (bytevector-ieee-single-native-set! vec (* i 4) x))
517(define-primitive-expander f32vector-ref (vec i)
518 (bytevector-ieee-single-native-ref vec (* i 4)))
519(define-primitive-expander f32vector-set! (vec i x)
520 (bytevector-ieee-single-native-set! vec (* i 4) x))
521
522(define-primitive-expander f64vector-ref (vec i)
523 (bytevector-ieee-double-native-ref vec (* i 8)))
524(define-primitive-expander f64vector-set! (vec i x)
525 (bytevector-ieee-double-native-set! vec (* i 8) x))
526(define-primitive-expander f64vector-ref (vec i)
527 (bytevector-ieee-double-native-ref vec (* i 8)))
528(define-primitive-expander f64vector-set! (vec i x)
529 (bytevector-ieee-double-native-set! vec (* i 8) x))
1bf78495 530
58147d67
MW
531(define (chained-comparison-expander prim-name)
532 (case-lambda
533 ((src) (make-const src #t))
534 ((src a) #f)
535 ((src a b) #f)
536 ((src a b . rest)
04f59ec2 537 (let* ((b-sym (gensym "b"))
58147d67
MW
538 (b* (make-lexical-ref src 'b b-sym)))
539 (make-let src
540 '(b)
541 (list b-sym)
542 (list b)
543 (make-conditional src
04f59ec2
AW
544 (make-primcall src prim-name (list a b*))
545 (make-primcall src prim-name (cons b* rest))
58147d67
MW
546 (make-const src #f)))))))
547
548(for-each (lambda (prim-name)
549 (hashq-set! *primitive-expand-table* prim-name
550 (chained-comparison-expander prim-name)))
551 '(< > <= >= =))
552
75a5de18 553;; Appropriate for use with either 'eqv?' or 'equal?'.
62d3430c 554(define (maybe-simplify-to-eq prim)
75a5de18 555 (case-lambda
62d3430c
MW
556 ((src) (make-const src #t))
557 ((src a) (make-const src #t))
75a5de18
MW
558 ((src a b)
559 ;; Simplify cases where either A or B is constant.
560 (define (maybe-simplify a b)
561 (and (const? a)
562 (let ((v (const-exp a)))
563 (and (or (memq v '(#f #t () #nil))
564 (symbol? v)
565 (and (integer? v)
566 (exact? v)
fa980bcc
MW
567 (<= v most-positive-fixnum)
568 (>= v most-negative-fixnum)))
569 (make-primcall src 'eq? (list a b))))))
75a5de18 570 (or (maybe-simplify a b) (maybe-simplify b a)))
62d3430c
MW
571 ((src a b . rest)
572 (make-conditional src (make-primcall src prim (list a b))
573 (make-primcall src prim (cons b rest))
574 (make-const src #f)))
75a5de18
MW
575 (else #f)))
576
62d3430c
MW
577(hashq-set! *primitive-expand-table* 'eqv? (maybe-simplify-to-eq 'eqv?))
578(hashq-set! *primitive-expand-table* 'equal? (maybe-simplify-to-eq 'equal?))
579
580(define (expand-chained-comparisons prim)
581 (case-lambda
582 ((src) (make-const src #t))
583 ((src a) (make-const src #t))
584 ((src a b) #f)
585 ((src a b . rest)
586 (make-conditional src (make-primcall src prim (list a b))
587 (make-primcall src prim (cons b rest))
588 (make-const src #f)))
589 (else #f)))
590
591(for-each (lambda (prim)
592 (hashq-set! *primitive-expand-table* prim
593 (expand-chained-comparisons prim)))
594 '(< <= = >= > eq?))
2446f8e1 595
9b2a2a39 596(hashq-set! *primitive-expand-table*
8fc43b12 597 'call-with-prompt
9b2a2a39 598 (case-lambda
f828ab4f 599 ((src tag thunk handler)
178a4092 600 (make-prompt src #f tag thunk handler))
9b2a2a39 601 (else #f)))
f828ab4f 602
2d026f04 603(hashq-set! *primitive-expand-table*
38504994 604 'abort-to-prompt*
2d026f04
AW
605 (case-lambda
606 ((src tag tail-args)
607 (make-abort src tag '() tail-args))
608 (else #f)))
9b2a2a39 609(hashq-set! *primitive-expand-table*
8fc43b12 610 'abort-to-prompt
9b2a2a39 611 (case-lambda
6e84cb95 612 ((src tag . args)
2d026f04 613 (make-abort src tag args (make-const #f '())))
9b2a2a39 614 (else #f)))