1 ;;; open-coding primitive procedures
3 ;; Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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
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-16)
27 #:export (resolve-primitives! add-interesting-primitive!
28 expand-primitives! effect-free-primitive?))
30 (define *interesting-primitive-names*
32 call-with-values @call-with-values
33 call-with-current-continuation @call-with-current-continuation
38 + * - / 1- 1+ quotient remainder modulo
40 pair? null? list? acons cons cons*
49 caaar caadr cadar caddr cdaar cdadr cddar cdddr
51 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
52 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
54 vector-ref vector-set!
56 bytevector-u8-ref bytevector-u8-set!
57 bytevector-s8-ref bytevector-s8-set!
59 bytevector-u16-ref bytevector-u16-set!
60 bytevector-u16-native-ref bytevector-u16-native-set!
61 bytevector-s16-ref bytevector-s16-set!
62 bytevector-s16-native-ref bytevector-s16-native-set!
64 bytevector-u32-ref bytevector-u32-set!
65 bytevector-u32-native-ref bytevector-u32-native-set!
66 bytevector-s32-ref bytevector-s32-set!
67 bytevector-s32-native-ref bytevector-s32-native-set!
69 bytevector-u64-ref bytevector-u64-set!
70 bytevector-u64-native-ref bytevector-u64-native-set!
71 bytevector-s64-ref bytevector-s64-set!
72 bytevector-s64-native-ref bytevector-s64-native-set!
74 bytevector-ieee-single-ref bytevector-ieee-single-set!
75 bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
76 bytevector-ieee-double-ref bytevector-ieee-double-set!
77 bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!))
79 (define (add-interesting-primitive! name)
80 (hashq-set! *interesting-primitive-vars*
81 (module-variable (current-module) name)
84 (define *interesting-primitive-vars* (make-hash-table))
86 (for-each add-interesting-primitive! *interesting-primitive-names*)
88 (define *effect-free-primitives*
92 + * - / 1- 1+ quotient remainder modulo
94 pair? null? list? acons cons cons*
98 caaar caadr cadar caddr cdaar cdadr cddar cdddr
99 caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
100 cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
102 bytevector-u8-ref bytevector-s8-ref
103 bytevector-u16-ref bytevector-u16-native-ref
104 bytevector-s16-ref bytevector-s16-native-ref
105 bytevector-u32-ref bytevector-u32-native-ref
106 bytevector-s32-ref bytevector-s32-native-ref
107 bytevector-u64-ref bytevector-u64-native-ref
108 bytevector-s64-ref bytevector-s64-native-ref
109 bytevector-ieee-single-ref bytevector-ieee-single-native-ref
110 bytevector-ieee-double-ref bytevector-ieee-double-native-ref))
113 (define *effect-free-primitive-table* (make-hash-table))
115 (for-each (lambda (x) (hashq-set! *effect-free-primitive-table* x #t))
116 *effect-free-primitives*)
118 (define (effect-free-primitive? prim)
119 (hashq-ref *effect-free-primitive-table* prim))
121 (define (resolve-primitives! x mod)
125 ((<toplevel-ref> src name)
126 (and=> (hashq-ref *interesting-primitive-vars*
127 (module-variable mod name))
128 (lambda (name) (make-primitive-ref src name))))
129 ((<module-ref> src mod name public?)
130 ;; for the moment, we're disabling primitive resolution for
131 ;; public refs because resolve-interface can raise errors.
132 (let ((m (and (not public?) (resolve-module mod))))
134 (and=> (hashq-ref *interesting-primitive-vars*
135 (module-variable m name))
136 (lambda (name) (make-primitive-ref src name))))))
142 (define *primitive-expand-table* (make-hash-table))
144 (define (expand-primitives! x)
148 ((<application> src proc args)
149 (and (primitive-ref? proc)
150 (let ((expand (hashq-ref *primitive-expand-table*
151 (primitive-ref-name proc))))
152 (and expand (apply expand src args)))))
156 ;;; I actually did spend about 10 minutes trying to redo this with
157 ;;; syntax-rules. Patches appreciated.
159 (define-macro (define-primitive-expander sym . clauses)
160 (define (inline-args args)
161 (let lp ((in args) (out '()))
162 (cond ((null? in) `(list ,@(reverse out)))
163 ((symbol? in) `(cons* ,@(reverse out) ,in))
166 (cons `(make-application src (make-primitive-ref src ',(caar in))
167 ,(inline-args (cdar in)))
170 ;; assume it's locally bound
171 (lp (cdr in) (cons (car in) out)))
173 (lp (cdr in) (cons `(make-const src ,(car in)) out)))
175 (error "what what" (car in))))))
176 (define (consequent exp)
180 ((if ,test ,then ,else)
185 `(make-application src (make-primitive-ref src ',(car exp))
186 ,(inline-args (cdr exp))))))
188 ;; assume locally bound
191 `(make-const src ,exp))
192 (else (error "bad consequent yall" exp))))
193 `(hashq-set! *primitive-expand-table*
196 ,@(let lp ((in clauses) (out '()))
198 (reverse (cons '(else #f) out))
200 (cons `((src . ,(car in))
201 ,(consequent (cadr in))) out)))))))
203 (define-primitive-expander zero? (x)
206 (define-primitive-expander +
209 (x y) (if (and (const? y)
210 (let ((y (const-exp y)))
211 (and (number? y) (exact? y) (= y 1))))
214 (let ((y (const-exp y)))
215 (and (number? y) (exact? y) (= y -1))))
218 (let ((x (const-exp x)))
219 (and (number? y) (exact? x) (= x 1))))
222 (x y z . rest) (+ x (+ y z . rest)))
224 (define-primitive-expander *
227 (x y z . rest) (* x (* y z . rest)))
229 (define-primitive-expander -
231 (x y) (if (and (const? y)
232 (let ((y (const-exp y)))
233 (and (number? y) (exact? y) (= y 1))))
236 (x y z . rest) (- x (+ y z . rest)))
238 (define-primitive-expander /
240 (x y z . rest) (/ x (* y z . rest)))
242 (define-primitive-expander caar (x) (car (car x)))
243 (define-primitive-expander cadr (x) (car (cdr x)))
244 (define-primitive-expander cdar (x) (cdr (car x)))
245 (define-primitive-expander cddr (x) (cdr (cdr x)))
246 (define-primitive-expander caaar (x) (car (car (car x))))
247 (define-primitive-expander caadr (x) (car (car (cdr x))))
248 (define-primitive-expander cadar (x) (car (cdr (car x))))
249 (define-primitive-expander caddr (x) (car (cdr (cdr x))))
250 (define-primitive-expander cdaar (x) (cdr (car (car x))))
251 (define-primitive-expander cdadr (x) (cdr (car (cdr x))))
252 (define-primitive-expander cddar (x) (cdr (cdr (car x))))
253 (define-primitive-expander cdddr (x) (cdr (cdr (cdr x))))
254 (define-primitive-expander caaaar (x) (car (car (car (car x)))))
255 (define-primitive-expander caaadr (x) (car (car (car (cdr x)))))
256 (define-primitive-expander caadar (x) (car (car (cdr (car x)))))
257 (define-primitive-expander caaddr (x) (car (car (cdr (cdr x)))))
258 (define-primitive-expander cadaar (x) (car (cdr (car (car x)))))
259 (define-primitive-expander cadadr (x) (car (cdr (car (cdr x)))))
260 (define-primitive-expander caddar (x) (car (cdr (cdr (car x)))))
261 (define-primitive-expander cadddr (x) (car (cdr (cdr (cdr x)))))
262 (define-primitive-expander cdaaar (x) (cdr (car (car (car x)))))
263 (define-primitive-expander cdaadr (x) (cdr (car (car (cdr x)))))
264 (define-primitive-expander cdadar (x) (cdr (car (cdr (car x)))))
265 (define-primitive-expander cdaddr (x) (cdr (car (cdr (cdr x)))))
266 (define-primitive-expander cddaar (x) (cdr (cdr (car (car x)))))
267 (define-primitive-expander cddadr (x) (cdr (cdr (car (cdr x)))))
268 (define-primitive-expander cdddar (x) (cdr (cdr (cdr (car x)))))
269 (define-primitive-expander cddddr (x) (cdr (cdr (cdr (cdr x)))))
271 (define-primitive-expander cons*
274 (x y . rest) (cons x (cons* y . rest)))
276 (define-primitive-expander acons (x y z)
279 (define-primitive-expander apply (f . args)
282 (define-primitive-expander call-with-values (producer consumer)
283 (@call-with-values producer consumer))
285 (define-primitive-expander call-with-current-continuation (proc)
286 (@call-with-current-continuation proc))
288 (define-primitive-expander call/cc (proc)
289 (@call-with-current-continuation proc))
291 (define-primitive-expander values (x) x)