Fixed a Scheme translation bug; cleaned compilation with GCC 4.
[bpt/guile.git] / module / language / scheme / translate.scm
CommitLineData
c7228382
KN
1;;; Guile Scheme specification
2
3;; Copyright (C) 2001 Free Software Foundation, Inc.
4
5;; This program is free software; you can redistribute it and/or modify
6;; it under the terms of the GNU General Public License as published by
7;; the Free Software Foundation; either version 2, or (at your option)
8;; any later version.
9;;
10;; This program 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
13;; GNU General Public License for more details.
14;;
15;; You should have received a copy of the GNU General Public License
16;; along with this program; see the file COPYING. If not, write to
17;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18;; Boston, MA 02111-1307, USA.
19
20;;; Code:
21
22(define-module (language scheme translate)
23 :use-module (system base language)
24 :use-module (system il ghil)
25 :use-module (ice-9 match)
26 :use-module (ice-9 receive)
27 :export (translate))
28
29(define (translate x e)
30 (call-with-ghil-environment (make-ghil-mod e) '()
31 (lambda (env vars)
ac99cb0c 32 (<ghil-lambda> env #f vars #f (trans env #f x)))))
c7228382
KN
33
34\f
35;;;
36;;; Translator
37;;;
38
8f5cfc81
KN
39(define scheme-primitives
40 '(not null? eq? eqv? equal? pair? list? cons car cdr set-car! set-cdr!))
41
c7228382
KN
42(define (trans e l x)
43 (cond ((pair? x)
44 (let ((y (macroexpand x)))
45 (if (eq? x y)
b6368dbb
LC
46 (trans-pair e (or (location x) l) (car x) (cdr x))
47 (trans e l y))))
f21dfea6 48 ((symbol? x)
ac99cb0c
KN
49 (let ((y (symbol-expand x)))
50 (if (symbol? y)
b6368dbb
LC
51 (<ghil-ref> e l (ghil-lookup e y))
52 (trans e l y))))
ac99cb0c 53 (else (<ghil-quote> e l x))))
c7228382 54
ac99cb0c 55(define (symbol-expand x)
f21dfea6
KN
56 (let loop ((s (symbol->string x)))
57 (let ((i (string-rindex s #\.)))
58 (if i
ac99cb0c
KN
59 (let ((sym (string->symbol (substring s (1+ i)))))
60 `(slot ,(loop (substring s 0 i)) (quote ,sym)))
61 (string->symbol s)))))
f21dfea6 62
c7228382
KN
63(define (trans-pair e l head tail)
64 (define (trans:x x) (trans e l x))
65 (define (trans:pair x) (trans-pair e l (car x) (cdr x)))
66 (define (trans:body body) (trans-body e l body))
ac99cb0c 67 (define (make:void) (<ghil-void> e l))
c7228382
KN
68 (define (bad-syntax)
69 (syntax-error l (format #f "bad ~A" head) (cons head tail)))
70 (case head
71 ;; (void)
72 ((void)
73 (match tail
74 (() (make:void))
75 (else (bad-syntax))))
76
77 ;; (quote OBJ)
78 ((quote)
79 (match tail
ac99cb0c 80 ((obj) (<ghil-quote> e l obj))
c7228382
KN
81 (else (bad-syntax))))
82
83 ;; (quasiquote OBJ)
84 ((quasiquote)
85 (match tail
ac99cb0c 86 ((obj) (<ghil-quasiquote> e l (trans-quasiquote e l obj)))
c7228382
KN
87 (else (bad-syntax))))
88
89 ((define define-private)
90 (match tail
91 ;; (define NAME VAL)
92 (((? symbol? name) val)
ac99cb0c 93 (<ghil-define> e l (ghil-lookup e name) (trans:x val)))
c7228382
KN
94
95 ;; (define (NAME FORMALS...) BODY...)
96 ((((? symbol? name) . formals) . body)
97 ;; -> (define NAME (lambda FORMALS BODY...))
98 (let ((val (trans:x `(lambda ,formals ,@body))))
ac99cb0c 99 (<ghil-define> e l (ghil-lookup e name) val)))
c7228382
KN
100
101 (else (bad-syntax))))
102
103 ((set!)
104 (match tail
105 ;; (set! NAME VAL)
106 (((? symbol? name) val)
ac99cb0c 107 (<ghil-set> e l (ghil-lookup e name) (trans:x val)))
c7228382
KN
108
109 ;; (set! (NAME ARGS...) VAL)
110 ((((? symbol? name) . args) val)
111 ;; -> ((setter NAME) ARGS... VAL)
b6368dbb 112 (trans:pair `((setter ,name) . (,@args ,val))))
c7228382
KN
113
114 (else (bad-syntax))))
115
116 ;; (if TEST THEN [ELSE])
117 ((if)
118 (match tail
119 ((test then)
ac99cb0c 120 (<ghil-if> e l (trans:x test) (trans:x then) (make:void)))
c7228382 121 ((test then else)
ac99cb0c 122 (<ghil-if> e l (trans:x test) (trans:x then) (trans:x else)))
c7228382
KN
123 (else (bad-syntax))))
124
125 ;; (and EXPS...)
126 ((and)
ac99cb0c 127 (<ghil-and> e l (map trans:x tail)))
c7228382
KN
128
129 ;; (or EXPS...)
130 ((or)
ac99cb0c 131 (<ghil-or> e l (map trans:x tail)))
c7228382
KN
132
133 ;; (begin EXPS...)
134 ((begin)
ac99cb0c 135 (<ghil-begin> e l (map trans:x tail)))
c7228382
KN
136
137 ((let)
138 (match tail
139 ;; (let NAME ((SYM VAL) ...) BODY...)
140 (((? symbol? name) (((? symbol? sym) val) ...) body ...)
141 ;; -> (letrec ((NAME (lambda (SYM...) BODY...))) (NAME VAL...))
142 (trans:pair `(letrec ((,name (lambda ,sym ,@body))) (,name ,@val))))
143
144 ;; (let () BODY...)
145 ((() body ...)
146 ;; NOTE: This differs from `begin'
ac99cb0c 147 (<ghil-begin> e l (list (trans:body body))))
c7228382
KN
148
149 ;; (let ((SYM VAL) ...) BODY...)
150 (((((? symbol? sym) val) ...) body ...)
151 (let ((vals (map trans:x val)))
152 (call-with-ghil-bindings e sym
153 (lambda (vars)
ac99cb0c 154 (<ghil-bind> e l vars vals (trans:body body))))))
c7228382
KN
155
156 (else (bad-syntax))))
157
158 ;; (let* ((SYM VAL) ...) BODY...)
159 ((let*)
160 (match tail
161 (((def ...) body ...)
162 (if (null? def)
163 (trans:pair `(let () ,@body))
164 (trans:pair `(let (,(car def)) (let* ,(cdr def) ,@body)))))
165 (else (bad-syntax))))
166
167 ;; (letrec ((SYM VAL) ...) BODY...)
168 ((letrec)
169 (match tail
170 (((((? symbol? sym) val) ...) body ...)
171 (call-with-ghil-bindings e sym
172 (lambda (vars)
173 (let ((vals (map trans:x val)))
ac99cb0c 174 (<ghil-bind> e l vars vals (trans:body body))))))
c7228382
KN
175 (else (bad-syntax))))
176
177 ;; (cond (CLAUSE BODY...) ...)
178 ((cond)
179 (match tail
180 (() (make:void))
181 ((('else . body)) (trans:body body))
182 (((test) . rest) (trans:pair `(or ,test (cond ,@rest))))
183 (((test '=> proc) . rest)
184 (trans:pair `(let ((_t ,test)) (if _t (,proc _t) (cond ,@rest)))))
185 (((test . body) . rest)
186 (trans:pair `(if ,test (begin ,@body) (cond ,@rest))))
187 (else (bad-syntax))))
188
189 ;; (case EXP ((KEY...) BODY...) ...)
190 ((case)
191 (match tail
192 ((exp . clauses)
193 (trans:pair
194 `(let ((_t ,exp))
195 ,(let loop ((ls clauses))
196 (cond ((null? ls) '(void))
197 ((eq? (caar ls) 'else) `(begin ,@(cdar ls)))
198 (else `(if (memv _t ',(caar ls))
199 (begin ,@(cdar ls))
200 ,(loop (cdr ls)))))))))
201 (else (bad-syntax))))
202
203 ;; (do ((SYM VAL [UPDATE]) ...) (TEST RESULT...) BODY...)
204 ((do)
205 (let ()
206 (define (next s x) (if (pair? x) (car x) s))
207 (match tail
208 ((((sym init . update) ...) (test . result) body ...)
209 (trans:pair
210 `(letrec ((_l (lambda ,sym
211 (if ,test
212 (let () (void) ,@result)
213 (let () (void) ,@body
214 (_l ,@(map next sym update)))))))
215 (_l ,@init))))
216 (else (bad-syntax)))))
217
218 ;; (lambda FORMALS BODY...)
219 ((lambda)
220 (match tail
221 ((formals body ...)
222 (receive (syms rest) (parse-formals formals)
223 (call-with-ghil-environment e syms
224 (lambda (env vars)
ac99cb0c 225 (<ghil-lambda> env l vars rest (trans-body env l body))))))
c7228382
KN
226 (else (bad-syntax))))
227
228 ((eval-case)
229 (let loop ((x tail))
230 (match x
231 (() (make:void))
232 ((('else . body)) (trans:pair `(begin ,@body)))
233 (((((? symbol? key) ...) body ...) rest ...)
c7228382 234 (if (memq 'load-toplevel key)
8f5cfc81
KN
235 (begin
236 (primitive-eval `(begin ,@(copy-tree body)))
237 (trans:pair `(begin ,@body)))
c7228382
KN
238 (loop rest)))
239 (else (bad-syntax)))))
240
241 (else
8f5cfc81 242 (if (memq head scheme-primitives)
ac99cb0c
KN
243 (<ghil-inline> e l head (map trans:x tail))
244 (<ghil-call> e l (trans:x head) (map trans:x tail))))))
c7228382
KN
245
246(define (trans-quasiquote e l x)
247 (cond ((not (pair? x)) x)
248 ((memq (car x) '(unquote unquote-splicing))
249 (let ((l (location x)))
250 (match (cdr x)
251 ((obj)
252 (if (eq? (car x) 'unquote)
ac99cb0c
KN
253 (<ghil-unquote> e l (trans e l obj))
254 (<ghil-unquote-splicing> e l (trans e l obj))))
c7228382
KN
255 (else (syntax-error l (format #f "bad ~A" (car x)) x)))))
256 (else (cons (trans-quasiquote e l (car x))
257 (trans-quasiquote e l (cdr x))))))
258
259(define (trans-body e l body)
260 (define (define->binding df)
261 (match (cdr df)
262 (((? symbol? name) val) (list name val))
263 ((((? symbol? name) . formals) . body)
264 (list name `(lambda ,formals ,@body)))
265 (else (syntax-error (location df) "bad define" df))))
266 ;; main
267 (let loop ((ls body) (ds '()))
268 (cond ((null? ls) (syntax-error l "bad body" body))
269 ((and (pair? (car ls)) (eq? (caar ls) 'define))
270 (loop (cdr ls) (cons (car ls) ds)))
271 (else
272 (if (null? ds)
273 (trans-pair e l 'begin ls)
274 (trans-pair e l 'letrec (cons (map define->binding ds) ls)))))))
275
276(define (parse-formals formals)
277 (cond
278 ;; (lambda x ...)
279 ((symbol? formals) (values (list formals) #t))
280 ;; (lambda (x y z) ...)
281 ((list? formals) (values formals #f))
282 ;; (lambda (x y . z) ...)
283 ((pair? formals)
284 (let loop ((l formals) (v '()))
285 (if (pair? l)
286 (loop (cdr l) (cons (car l) v))
287 (values (reverse! (cons l v)) #t))))
288 (else (syntax-error (location formals) "bad formals" formals))))
289
290(define (location x)
291 (and (pair? x)
292 (let ((props (source-properties x)))
293 (and (not (null? props))
294 (cons (assq-ref props 'line) (assq-ref props 'column))))))