Commit | Line | Data |
---|---|---|
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)))))) |