1 ;;; Guile Scheme specification
3 ;; Copyright (C) 2001 Free Software Foundation, Inc.
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)
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.
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.
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)
29 (define (translate x e)
30 (call-with-ghil-environment (make-ghil-mod e) '()
32 (make-<ghil-lambda> env #f vars 0 (trans env #f x)))))
41 (let ((y (macroexpand x)))
43 (trans-pair e (or (location x) l) (car x) (cdr x))
45 ((symbol? x) (make-<ghil-ref> e l (ghil-lookup e x)))
46 (else (make-<ghil-quote> e l x))))
48 (define (trans-pair e l head tail)
49 (define (trans:x x) (trans e l x))
50 (define (trans:pair x) (trans-pair e l (car x) (cdr x)))
51 (define (trans:body body) (trans-body e l body))
52 (define (make:void) (make-<ghil-void> e l))
54 (syntax-error l (format #f "bad ~A" head) (cons head tail)))
65 ((obj) (make-<ghil-quote> e l obj))
71 ((obj) (make-<ghil-quasiquote> e l (trans-quasiquote e l obj)))
74 ((define define-private)
77 (((? symbol? name) val)
78 (make-<ghil-define> e l (ghil-lookup e name) (trans:x val)))
80 ;; (define (NAME FORMALS...) BODY...)
81 ((((? symbol? name) . formals) . body)
82 ;; -> (define NAME (lambda FORMALS BODY...))
83 (let ((val (trans:x `(lambda ,formals ,@body))))
84 (make-<ghil-define> e l (ghil-lookup e name) val)))
91 (((? symbol? name) val)
92 (make-<ghil-set> e l (ghil-lookup e name) (trans:x val)))
94 ;; (set! (NAME ARGS...) VAL)
95 ((((? symbol? name) . args) val)
96 ;; -> ((setter NAME) ARGS... VAL)
97 (trans:pair `((setter ,name) (,@args ,val))))
101 ;; (if TEST THEN [ELSE])
105 (make-<ghil-if> e l (trans:x test) (trans:x then) (make:void)))
107 (make-<ghil-if> e l (trans:x test) (trans:x then) (trans:x else)))
108 (else (bad-syntax))))
112 (make-<ghil-and> e l (map trans:x tail)))
116 (make-<ghil-or> e l (map trans:x tail)))
120 (make-<ghil-begin> e l (map trans:x tail)))
124 ;; (let NAME ((SYM VAL) ...) BODY...)
125 (((? symbol? name) (((? symbol? sym) val) ...) body ...)
126 ;; -> (letrec ((NAME (lambda (SYM...) BODY...))) (NAME VAL...))
127 (trans:pair `(letrec ((,name (lambda ,sym ,@body))) (,name ,@val))))
131 ;; NOTE: This differs from `begin'
132 (make-<ghil-begin> e l (list (trans:body body))))
134 ;; (let ((SYM VAL) ...) BODY...)
135 (((((? symbol? sym) val) ...) body ...)
136 (let ((vals (map trans:x val)))
137 (call-with-ghil-bindings e sym
139 (make-<ghil-bind> e l vars vals (trans:body body))))))
141 (else (bad-syntax))))
143 ;; (let* ((SYM VAL) ...) BODY...)
146 (((def ...) body ...)
148 (trans:pair `(let () ,@body))
149 (trans:pair `(let (,(car def)) (let* ,(cdr def) ,@body)))))
150 (else (bad-syntax))))
152 ;; (letrec ((SYM VAL) ...) BODY...)
155 (((((? symbol? sym) val) ...) body ...)
156 (call-with-ghil-bindings e sym
158 (let ((vals (map trans:x val)))
159 (make-<ghil-bind> e l vars vals (trans:body body))))))
160 (else (bad-syntax))))
162 ;; (cond (CLAUSE BODY...) ...)
166 ((('else . body)) (trans:body body))
167 (((test) . rest) (trans:pair `(or ,test (cond ,@rest))))
168 (((test '=> proc) . rest)
169 (trans:pair `(let ((_t ,test)) (if _t (,proc _t) (cond ,@rest)))))
170 (((test . body) . rest)
171 (trans:pair `(if ,test (begin ,@body) (cond ,@rest))))
172 (else (bad-syntax))))
174 ;; (case EXP ((KEY...) BODY...) ...)
180 ,(let loop ((ls clauses))
181 (cond ((null? ls) '(void))
182 ((eq? (caar ls) 'else) `(begin ,@(cdar ls)))
183 (else `(if (memv _t ',(caar ls))
185 ,(loop (cdr ls)))))))))
186 (else (bad-syntax))))
188 ;; (do ((SYM VAL [UPDATE]) ...) (TEST RESULT...) BODY...)
191 (define (next s x) (if (pair? x) (car x) s))
193 ((((sym init . update) ...) (test . result) body ...)
195 `(letrec ((_l (lambda ,sym
197 (let () (void) ,@result)
198 (let () (void) ,@body
199 (_l ,@(map next sym update)))))))
201 (else (bad-syntax)))))
203 ;; (lambda FORMALS BODY...)
207 (receive (syms rest) (parse-formals formals)
208 (call-with-ghil-environment e syms
210 (make-<ghil-lambda> env l vars rest (trans-body env l body))))))
211 (else (bad-syntax))))
217 ((('else . body)) (trans:pair `(begin ,@body)))
218 (((((? symbol? key) ...) body ...) rest ...)
219 (if (memq 'compile key)
220 (primitive-eval `(begin ,@(copy-tree body))))
221 (if (memq 'load-toplevel key)
222 (trans:pair `(begin ,@body))
224 (else (bad-syntax)))))
227 (make-<ghil-call> e l (trans:x head) (map trans:x tail)))))
229 (define (trans-quasiquote e l x)
230 (cond ((not (pair? x)) x)
231 ((memq (car x) '(unquote unquote-splicing))
232 (let ((l (location x)))
235 (if (eq? (car x) 'unquote)
236 (make-<ghil-unquote> e l (trans e l obj))
237 (make-<ghil-unquote-splicing> e l (trans e l obj))))
238 (else (syntax-error l (format #f "bad ~A" (car x)) x)))))
239 (else (cons (trans-quasiquote e l (car x))
240 (trans-quasiquote e l (cdr x))))))
242 (define (trans-body e l body)
243 (define (define->binding df)
245 (((? symbol? name) val) (list name val))
246 ((((? symbol? name) . formals) . body)
247 (list name `(lambda ,formals ,@body)))
248 (else (syntax-error (location df) "bad define" df))))
250 (let loop ((ls body) (ds '()))
251 (cond ((null? ls) (syntax-error l "bad body" body))
252 ((and (pair? (car ls)) (eq? (caar ls) 'define))
253 (loop (cdr ls) (cons (car ls) ds)))
256 (trans-pair e l 'begin ls)
257 (trans-pair e l 'letrec (cons (map define->binding ds) ls)))))))
259 (define (parse-formals formals)
262 ((symbol? formals) (values (list formals) #t))
263 ;; (lambda (x y z) ...)
264 ((list? formals) (values formals #f))
265 ;; (lambda (x y . z) ...)
267 (let loop ((l formals) (v '()))
269 (loop (cdr l) (cons (car l) v))
270 (values (reverse! (cons l v)) #t))))
271 (else (syntax-error (location formals) "bad formals" formals))))
275 (let ((props (source-properties x)))
276 (and (not (null? props))
277 (cons (assq-ref props 'line) (assq-ref props 'column))))))