3
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5
2006, 2007, 2008, 2009, 2010 Massachusetts Institute of Technology
7
This file is part of MIT/GNU Scheme.
9
MIT/GNU Scheme is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or (at
12
your option) any later version.
14
MIT/GNU Scheme is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with MIT/GNU Scheme; if not, write to the Free Software
21
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
26
;;;; MIT/GNU Scheme macros
28
(declare (usual-integrations))
32
(define-syntax :cond-expand
34
(lambda (form rename compare)
35
(let ((if-error (lambda () (ill-formed-syntax form))))
36
(if (syntax-match? '(+ (DATUM * FORM)) (cdr form))
37
(let loop ((clauses (cdr form)))
38
(let ((req (caar clauses))
39
(if-true (lambda () `(,(rename 'BEGIN) ,@(cdar clauses)))))
40
(if (and (identifier? req)
41
(compare (rename 'ELSE) req))
42
(if (null? (cdr clauses))
50
(if (null? (cdr clauses))
52
(loop (cdr clauses))))))
53
(cond ((identifier? req)
54
(if (any (lambda (feature)
55
(compare (rename feature) req))
56
supported-srfi-features)
59
((and (syntax-match? '(IDENTIFIER DATUM) req)
60
(compare (rename 'NOT) (car req)))
64
((and (syntax-match? '(IDENTIFIER * DATUM) req)
65
(compare (rename 'AND) (car req)))
66
(let and-loop ((reqs (cdr req)))
69
(lambda () (and-loop (cdr reqs)))
72
((and (syntax-match? '(IDENTIFIER * DATUM) req)
73
(compare (rename 'OR) (car req)))
74
(let or-loop ((reqs (cdr req)))
78
(lambda () (or-loop (cdr reqs))))
84
(define supported-srfi-features
90
SRFI-6 ;Basic String Ports
92
SRFI-9 ;DEFINE-RECORD-TYPE
94
SRFI-27 ;Sources of Random Bits
95
SRFI-30 ;Nested Multi-Line Comments (#| ... |#)
96
SRFI-62 ;S-expression comments
97
SRFI-69 ;Basic Hash Tables
100
(define-syntax :receive
101
(er-macro-transformer
102
(lambda (form rename compare)
104
(if (syntax-match? '(R4RS-BVL FORM + FORM) (cdr form))
105
`(,(rename 'CALL-WITH-VALUES)
106
(,(rename 'LAMBDA) () ,(caddr form))
107
(,(rename 'LAMBDA) ,(cadr form) ,@(cdddr form)))
108
(ill-formed-syntax form)))))
110
(define-syntax :define-record-type
111
(er-macro-transformer
112
(lambda (form rename compare)
114
(if (syntax-match? '(IDENTIFIER
115
(IDENTIFIER * IDENTIFIER)
117
* (IDENTIFIER IDENTIFIER ? IDENTIFIER))
119
(let ((type (cadr form))
120
(constructor (car (caddr form)))
121
(c-tags (cdr (caddr form)))
122
(predicate (cadddr form))
123
(fields (cddddr form))
124
(de (rename 'DEFINE)))
126
(,de ,type (,(rename 'MAKE-RECORD-TYPE) ',type ',(map car fields)))
127
(,de ,constructor (,(rename 'RECORD-CONSTRUCTOR) ,type ',c-tags))
128
(,de ,predicate (,(rename 'RECORD-PREDICATE) ,type))
131
(let ((name (car field)))
132
(cons `(,de ,(cadr field)
133
(,(rename 'RECORD-ACCESSOR) ,type ',name))
134
(if (pair? (cddr field))
135
`((,de ,(caddr field)
136
(,(rename 'RECORD-MODIFIER) ,type ',name)))
139
(ill-formed-syntax form)))))
141
(define-syntax :define
142
(er-macro-transformer
143
(lambda (form rename compare)
145
(receive (name value) (parse-define-form form rename)
146
`(,keyword:define ,name ,value)))))
148
(define (parse-define-form form rename)
149
(cond ((syntax-match? '((DATUM . MIT-BVL) + FORM) (cdr form))
151
`(,(car form) ,(caadr form)
152
,(if (identifier? (caadr form))
153
`(,(rename 'NAMED-LAMBDA) ,@(cdr form))
154
`(,(rename 'LAMBDA) ,(cdadr form) ,@(cddr form))))
156
((syntax-match? '(IDENTIFIER ? EXPRESSION) (cdr form))
158
(if (pair? (cddr form))
160
(unassigned-expression))))
162
(ill-formed-syntax form))))
165
(er-macro-transformer
166
(lambda (form rename compare)
168
(cond ((syntax-match? '(IDENTIFIER (* (IDENTIFIER ? EXPRESSION)) + FORM)
170
(let ((name (cadr form))
171
(bindings (caddr form))
174
((,name (,(rename 'NAMED-LAMBDA) (,name ,@(map car bindings))
177
,@(map (lambda (binding)
178
(if (pair? (cdr binding))
180
(unassigned-expression)))
182
((syntax-match? '((* (IDENTIFIER ? EXPRESSION)) + FORM) (cdr form))
183
`(,keyword:let ,@(cdr (normalize-let-bindings form))))
185
(ill-formed-syntax form))))))
187
(define (normalize-let-bindings form)
188
`(,(car form) ,(map (lambda (binding)
189
(if (pair? (cdr binding))
191
(list (car binding) (unassigned-expression))))
196
(er-macro-transformer
197
(lambda (form rename compare)
198
rename compare ;ignore
199
(expand/let* form (rename 'LET)))))
201
(define-syntax :let*-syntax
202
(er-macro-transformer
203
(lambda (form rename compare)
204
rename compare ;ignore
205
(expand/let* form (rename 'LET-SYNTAX)))))
207
(define (expand/let* form let-keyword)
208
(syntax-check '(KEYWORD (* DATUM) + FORM) form)
209
(let ((bindings (cadr form))
212
(let loop ((bindings bindings))
213
(if (pair? (cdr bindings))
214
`(,let-keyword (,(car bindings)) ,(loop (cdr bindings)))
215
`(,let-keyword ,bindings ,@body)))
216
`(,let-keyword ,bindings ,@body))))
219
(er-macro-transformer
220
(lambda (form rename compare)
222
(syntax-check '(KEYWORD * EXPRESSION) form)
223
(let ((operands (cdr form)))
225
(let ((if-keyword (rename 'IF)))
226
(let loop ((operands operands))
227
(if (pair? (cdr operands))
228
`(,if-keyword ,(car operands)
229
,(loop (cdr operands))
235
(er-macro-transformer
236
(lambda (form rename compare)
237
(syntax-check '(KEYWORD EXPRESSION + (DATUM * EXPRESSION)) form)
240
(lambda (clause rest)
241
(cond ((null? (car clause))
243
((and (identifier? (car clause))
244
(compare (rename 'ELSE) (car clause))
246
`(,(rename 'BEGIN) ,@(cdr clause)))
247
((list? (car clause))
248
`(,(rename 'IF) ,(process-predicate (car clause))
249
(,(rename 'BEGIN) ,@(cdr clause))
250
,(process-rest rest)))
252
(syntax-error "Ill-formed clause:" clause)))))
256
(process-clause (car rest) (cdr rest))
257
(unspecific-expression))))
260
;; Optimize predicate for speed in compiled code.
261
(cond ((null? (cdr items))
262
(single-test (car items)))
263
((null? (cddr items))
264
`(,(rename 'OR) ,(single-test (car items))
265
,(single-test (cadr items))))
266
((null? (cdddr items))
267
`(,(rename 'OR) ,(single-test (car items))
268
,(single-test (cadr items))
269
,(single-test (caddr items))))
270
((null? (cddddr items))
271
`(,(rename 'OR) ,(single-test (car items))
272
,(single-test (cadr items))
273
,(single-test (caddr items))
274
,(single-test (cadddr items))))
277
(if (for-all? items eq-testable?) 'MEMQ 'MEMV))
282
`(,(rename (if (eq-testable? item) 'EQ? 'EQV?))
289
;; remainder are implementation dependent:
291
(fix:fixnum? item)))))
292
`(,(rename 'LET) ((,(rename 'TEMP) ,(cadr form)))
293
,(process-clause (caddr form)
297
(er-macro-transformer
298
(lambda (form rename compare)
299
(let ((clauses (cdr form)))
300
(if (not (pair? clauses))
301
(syntax-error "Form must have at least one clause:" form))
302
(let loop ((clause (car clauses)) (rest (cdr clauses)))
303
(expand/cond-clause clause rename compare (null? rest)
305
(loop (car rest) (cdr rest))
306
(unspecific-expression))))))))
309
(er-macro-transformer
310
(lambda (form rename compare)
311
(syntax-check '(KEYWORD (* (IDENTIFIER EXPRESSION ? EXPRESSION))
315
(let ((bindings (cadr form))
316
(r-loop (rename 'DO-LOOP)))
319
,(map (lambda (binding)
320
(list (car binding) (cadr binding)))
322
,(expand/cond-clause (caddr form) rename compare #f
325
(,r-loop ,@(map (lambda (binding)
326
(if (pair? (cddr binding))
331
(define (expand/cond-clause clause rename compare else-allowed? alternative)
332
(if (not (and (pair? clause) (list? (cdr clause))))
333
(syntax-error "Ill-formed clause:" clause))
334
(cond ((and (identifier? (car clause))
335
(compare (rename 'ELSE) (car clause)))
336
(if (not else-allowed?)
337
(syntax-error "Misplaced ELSE clause:" clause))
338
(if (or (not (pair? (cdr clause)))
339
(and (identifier? (cadr clause))
340
(compare (rename '=>) (cadr clause))))
341
(syntax-error "Ill-formed ELSE clause:" clause))
342
`(,(rename 'BEGIN) ,@(cdr clause)))
343
((not (pair? (cdr clause)))
344
`(,(rename 'OR) ,(car clause) ,alternative))
345
((and (identifier? (cadr clause))
346
(compare (rename '=>) (cadr clause)))
347
(if (not (and (pair? (cddr clause))
348
(null? (cdddr clause))))
349
(syntax-error "Ill-formed => clause:" clause))
350
(let ((r-temp (rename 'TEMP)))
351
`(,(rename 'LET) ((,r-temp ,(car clause)))
352
(,(rename 'IF) ,r-temp
353
(,(caddr clause) ,r-temp)
356
`(,(rename 'IF) ,(car clause)
357
(,(rename 'BEGIN) ,@(cdr clause))
360
(define-syntax :quasiquote
361
(er-macro-transformer
362
(lambda (form rename compare)
364
(define (descend-quasiquote x level return)
365
(cond ((pair? x) (descend-quasiquote-pair x level return))
366
((vector? x) (descend-quasiquote-vector x level return))
367
(else (return 'QUOTE x))))
369
(define (descend-quasiquote-pair x level return)
370
(cond ((not (and (pair? x)
371
(identifier? (car x))
374
(descend-quasiquote-pair* x level return))
375
((compare (rename 'QUASIQUOTE) (car x))
376
(descend-quasiquote-pair* x (+ level 1) return))
377
((compare (rename 'UNQUOTE) (car x))
379
(return 'UNQUOTE (cadr x))
380
(descend-quasiquote-pair* x (- level 1) return)))
381
((compare (rename 'UNQUOTE-SPLICING) (car x))
383
(return 'UNQUOTE-SPLICING (cadr x))
384
(descend-quasiquote-pair* x (- level 1) return)))
386
(descend-quasiquote-pair* x level return))))
388
(define (descend-quasiquote-pair* x level return)
389
(descend-quasiquote (car x) level
390
(lambda (car-mode car-arg)
391
(descend-quasiquote (cdr x) level
392
(lambda (cdr-mode cdr-arg)
393
(cond ((and (eq? car-mode 'QUOTE) (eq? cdr-mode 'QUOTE))
395
((eq? car-mode 'UNQUOTE-SPLICING)
396
(if (and (eq? cdr-mode 'QUOTE) (null? cdr-arg))
397
(return 'UNQUOTE car-arg)
400
(finalize-quasiquote cdr-mode
402
((and (eq? cdr-mode 'QUOTE) (list? cdr-arg))
404
(cons (finalize-quasiquote car-mode car-arg)
405
(map (lambda (element)
406
(finalize-quasiquote 'QUOTE
409
((eq? cdr-mode 'LIST)
411
(cons (finalize-quasiquote car-mode car-arg)
416
(list (finalize-quasiquote car-mode car-arg)
417
(finalize-quasiquote cdr-mode cdr-arg))))))))))
419
(define (descend-quasiquote-vector x level return)
420
(descend-quasiquote (vector->list x) level
423
((QUOTE) (return 'QUOTE x))
424
((LIST) (return 'VECTOR arg))
426
(return 'LIST->VECTOR
427
(list (finalize-quasiquote mode arg))))))))
429
(define (finalize-quasiquote mode arg)
431
((QUOTE) `(,(rename 'QUOTE) ,arg))
433
((UNQUOTE-SPLICING) (syntax-error ",@ in illegal context:" arg))
434
(else `(,(rename mode) ,@arg))))
436
(syntax-check '(KEYWORD EXPRESSION) form)
437
(descend-quasiquote (cadr form) 0 finalize-quasiquote))))
439
;;;; SRFI 2: AND-LET*
441
;;; The SRFI document is a little unclear about the semantics, imposes
442
;;; the weird restriction that variables may be duplicated (citing
443
;;; LET*'s similar restriction, which doesn't actually exist), and the
444
;;; reference implementation is highly non-standard and hard to
445
;;; follow. This passes all of the tests except for the one that
446
;;; detects duplicate bound variables, though.
448
(define-syntax :and-let*
449
(er-macro-transformer
450
(lambda (form rename compare)
452
(let ((%and (rename 'AND))
454
(%begin (rename 'BEGIN)))
455
(cond ((syntax-match? '(() * FORM) (cdr form))
456
`(,%begin #T ,@(cddr form)))
457
((syntax-match? '((* DATUM) * FORM) (cdr form))
458
(let ((clauses (cadr form))
460
(define (expand clause recur)
461
(cond ((syntax-match? 'IDENTIFIER clause)
463
((syntax-match? '(EXPRESSION) clause)
464
(recur (car clause)))
465
((syntax-match? '(IDENTIFIER EXPRESSION) clause)
466
(let ((tail (recur (car clause))))
467
(and tail `(,%let (,clause) ,tail))))
469
(define (recur clauses make-body)
470
(expand (car clauses)
471
(let ((clauses (cdr clauses)))
476
,(recur clauses make-body)))))))
479
(lambda (conjunct) conjunct)
481
`(,%and ,conjunct (,%begin ,@body)))))
482
(ill-formed-syntax form))))
484
(ill-formed-syntax form)))))))
486
(define-syntax :access
487
(er-macro-transformer
488
(lambda (form rename compare)
489
rename compare ;ignore
490
(cond ((syntax-match? '(IDENTIFIER EXPRESSION) (cdr form))
491
`(,keyword:access ,@(cdr form)))
492
((syntax-match? '(IDENTIFIER IDENTIFIER + FORM) (cdr form))
493
`(,keyword:access ,(cadr form) (,(car form) ,@(cddr form))))
495
(ill-formed-syntax form))))))
497
(define-syntax :cons-stream
498
(er-macro-transformer
499
(lambda (form rename compare)
501
(syntax-check '(KEYWORD EXPRESSION EXPRESSION) form)
502
`(,(rename 'CONS) ,(cadr form)
503
(,(rename 'DELAY) ,(caddr form))))))
505
(define-syntax :define-integrable
506
(er-macro-transformer
507
(lambda (form rename compare)
509
(let ((r-begin (rename 'BEGIN))
510
(r-declare (rename 'DECLARE))
511
(r-define (rename 'DEFINE)))
512
(cond ((syntax-match? '(IDENTIFIER EXPRESSION) (cdr form))
514
(,r-declare (INTEGRATE ,(cadr form)))
515
(,r-define ,@(cdr form))))
516
((syntax-match? '((IDENTIFIER * IDENTIFIER) + FORM) (cdr form))
518
(,r-declare (INTEGRATE-OPERATOR ,(caadr form)))
519
(,r-define ,(cadr form)
520
(,r-declare (INTEGRATE ,@(cdadr form)))
523
(ill-formed-syntax form)))))))
525
(define-syntax :fluid-let
526
(er-macro-transformer
527
(lambda (form rename compare)
529
(syntax-check '(KEYWORD (* (FORM ? EXPRESSION)) + FORM) form)
530
(let ((names (map car (cadr form)))
531
(r-let (rename 'LET))
532
(r-lambda (rename 'LAMBDA))
533
(r-set! (rename 'SET!)))
537
(make-synthetic-identifier 'OUT-TEMP))
542
(make-synthetic-identifier 'IN-TEMP))
545
(lambda (tos names froms)
547
,@(map (lambda (to name from)
554
,(unspecific-expression)))))
555
`(,r-let (,@(map cons in-temps (map cdr (cadr form)))
556
,@(map list out-temps))
557
(,(rename 'SHALLOW-FLUID-BIND)
558
,(swap out-temps names in-temps)
559
(,r-lambda () ,@(cddr form))
560
,(swap in-temps names out-temps))))))))
562
(define (unspecific-expression)
563
`(,keyword:unspecific))
565
(define (unassigned-expression)
566
`(,keyword:unassigned))
b'\\ No newline at end of file'