trac.callcc.org

root/release/3/riaxpander/riaxpander-chicken-macros.scm

Revision 10322, 19.0 kB (checked in by ashinn, 8 months ago)

Adding support for compiled syntax extensions.

Line 
1 ;;;; riaxpander-chicken-macros.scm
2 ;;;; (adapted from syntactic-closures-chicken-macros.scm)
3
4 (define-syntax define-macro
5   (syntax-rules ()
6     ((_ (id . llist) . body)
7      (define-syntax id
8        (rsc-macro-transformer
9   (lambda (exp env)
10     (apply (lambda llist . body) (cdr exp))))))
11     ((_ id expander)
12      (define-syntax id
13        (rsc-macro-transformer
14   (lambda (exp env)
15     (apply expander (cdr exp))))))))
16
17 (define-syntax include
18   (rsc-macro-transformer
19    (lambda (exp env)
20      (syntax-check '(keyword expression) exp)
21      (let ((filename (cadr exp)))
22        (let ((path (##sys#resolve-include-filename filename #t)))
23    (if (load-verbose) (print "; including " path " ..."))
24    `(,(make-syntactic-closure env '() 'begin)
25      ,@(with-input-from-file path
26          (lambda ()
27      (do ((x (read) (read))
28           (xs '() (cons x xs)))
29          ((eof-object? x)
30           (reverse xs)))))))))))
31
32 (define-syntax cond-expand
33   (sc-macro-transformer
34    (lambda (form env)
35      (capture-syntactic-environment
36       (lambda (transformer-env)
37  
38   (define (err x)
39     (syntax-error "syntax error in `cond-expand' form" x form))
40   (define (literal=? usage-id transformer-id)
41     (and (identifier? usage-id)
42          (identifier=? env usage-id transformer-env transformer-id)))
43   (define (close-forms forms)
44     (map (lambda (form) (make-syntactic-closure env '() form)) forms))
45   (define (test fx)
46     (cond ((identifier? fx)
47      (##sys#feature? (identifier->symbol fx)))
48     ((not (pair? fx)) (err fx))
49     (else
50      (let ((bool (##sys#slot fx 0))
51            (rest (##sys#slot fx 1)))
52        (if (literal=? bool bool)
53            (case bool
54        ((and)
55         (or (eq? rest '())
56             (if (pair? rest)
57           (and (test (##sys#slot rest 0))
58                (test `(and ,@(##sys#slot rest 1))))
59           (err fx))))
60        ((or)
61         (and (not (eq? rest '()))
62              (if (pair? rest)
63            (or (test (##sys#slot rest 0))
64                (test `(or ,@(##sys#slot rest 1))))
65            (err fx))))
66        ((not) (not (test (cadr fx))))
67        (else (err fx)))
68            (err fx))))))
69
70   (let ((clauses (cdr form)))
71     (let expand ((cls clauses))
72       (cond ((null? cls)
73        (##sys#apply
74         ##sys#error "no matching clause in `cond-expand' form"
75         (map car clauses)))
76       ((not (pair? cls)) (err cls))
77       (else
78        (let ((clause (##sys#slot cls 0))
79        (rclauses (##sys#slot cls 1)))
80          (if (not (pair? clause))
81        (err clause)
82        (let ((id (##sys#slot clause 0)))
83          (cond ((literal=? id 'else)
84           (let ((rest (##sys#slot clause 1)))
85             (if (null? rest)
86           '(##core#undefined)
87           `(begin ,@(close-forms rest)))))
88          ((test id) `(begin ,@(close-forms
89                    (##sys#slot clause 1))))
90          (else (expand rclauses)))))))))))))))
91
92 (define-syntax when
93   (syntax-rules ()
94     ((_ x y z ...) (if x (begin y z ...)))))
95
96 (define-syntax unless
97   (syntax-rules ()
98     ((_ x y z ...) (if x (##core#undefined) (begin y z ...)))))
99
100 (define-syntax receive
101   (syntax-rules ()
102     ((_ vars) (##sys#call-with-values (lambda () vars) ##sys#list))
103     ((_ vars x0 x1 x2 ...)
104      (##sys#call-with-values
105       (lambda () x0)
106       (lambda vars x1 x2 ...)))))
107
108 (define-syntax time
109   (syntax-rules ()
110     ((_ exp ...)
111      (begin
112        (##sys#start-timer)
113        (##sys#call-with-values
114   (lambda () exp ...)
115   (lambda tmp
116     (##sys#display-times (##sys#stop-timer))
117     (##sys#apply ##sys#values tmp)))))))
118
119 (define-syntax assert
120   (syntax-rules ()
121     ((_ exp)
122      (assert exp (##core#immutable '"assertion failed")))
123     ((_ exp msg arg1 ...)
124      (if (##core#check exp)
125    (##core#undefined)
126    (##sys#error msg 'exp arg1 ...)))))
127
128 (define-syntax ensure
129   (syntax-rules ()
130     ((_ pred exp)
131      (let ((tmp exp))
132        (if (##core#check (pred tmp))
133      tmp
134            (##sys#error (##core#immutable '"argument has incorrect type") tmp 'pred))))
135     ((_ pred exp arg1 arg2 ...)
136      (let ((tmp exp))
137        (if (##core#check (pred tmp))
138            tmp
139            (##sys#error arg1 arg2 ...))))))
140
141 (define-syntax case-lambda    ; (reference implementation)
142   (syntax-rules ()
143     ((case-lambda
144       (?a1 ?e1 ...)
145       ?clause1 ...)
146      (lambda args
147        (let ((l (length args)))
148          (case-lambda "CLAUSE" args l
149                       (?a1 ?e1 ...)
150                       ?clause1 ...))))
151     ((case-lambda "CLAUSE" ?args ?l
152                   ((?a1 ...) ?e1 ...)
153                   ?clause1 ...)
154      (if (eq? ?l (length '(?a1 ...)))
155          (##sys#apply (lambda (?a1 ...) ?e1 ...) ?args)
156          (case-lambda "CLAUSE" ?args ?l
157                       ?clause1 ...)))
158     ((case-lambda "CLAUSE" ?args ?l
159                   ((?a1 . ?ar) ?e1 ...)
160                   ?clause1 ...)
161      (case-lambda "IMPROPER" ?args ?l 1 (?a1 . ?ar) (?ar ?e1 ...)
162                   ?clause1 ...))
163     ((case-lambda "CLAUSE" ?args ?l
164                   (?a1 ?e1 ...)
165                   ?clause1 ...)
166      (let ((?a1 ?args))
167        ?e1 ...))
168     ((case-lambda "CLAUSE" ?args ?l)
169      (##core#check (##sys#error (##core#immutable '"wrong number of arguments to CASE-LAMBDA."))))
170     ((case-lambda "IMPROPER" ?args ?l ?k ?al ((?a1 . ?ar) ?e1 ...)
171                   ?clause1 ...)
172      (case-lambda "IMPROPER" ?args ?l (+ ?k 1) ?al (?ar ?e1 ...)
173                   ?clause1 ...))
174     ((case-lambda "IMPROPER" ?args ?l ?k ?al (?ar ?e1 ...)
175                   ?clause1 ...)
176      (if (fx>= ?l ?k)
177          (##sys#apply (lambda ?al ?e1 ...) ?args)
178          (case-lambda "CLAUSE" ?args ?l
179                       ?clause1 ...)))))
180
181 (define-syntax and-let*
182   (syntax-rules ()
183     ((and-let* () body ...)
184      (begin body ...))
185
186     ((and-let* ((var expr) clauses ...) body ...)
187      (let ((var expr))
188        (if var (and-let* (clauses ...) body ...) #f)))
189
190     ((and-let* ((expr) clauses ...) body ...)
191      (if expr (and-let* (clauses ...) body ...) #f))
192    
193     ((and-let* (var clauses ...) body ...)
194      (if var (and-let* (clauses ...) body ...) #f))))
195
196 (define-syntax let*-values
197   (syntax-rules ()
198     ((_ () exp1 ...) (let () exp1 ...))
199     ((_ (binding0 binding1 ...) exp0 exp1 ...)
200      (let-values (binding0)
201        (let*-values (binding1 ...) exp0 exp1 ...)))))
202
203 (define-syntax let-values
204   (syntax-rules ()
205     ((let-values (?binding ...) ?body0 ?body1 ...)
206      (let-values "bind" (?binding ...) () (begin ?body0 ?body1 ...)))
207
208     ((let-values "bind" () ?tmps ?body)
209      (let ?tmps ?body))
210
211     ((let-values "bind" ((?b0 ?e0) ?binding ...) ?tmps ?body)
212      (let-values "mktmp" ?b0 ?e0 () (?binding ...) ?tmps ?body))
213
214     ((let-values "mktmp" () ?e0 ?args ?bindings ?tmps ?body)
215      (call-with-values
216        (lambda () ?e0)
217        (lambda ?args
218          (let-values "bind" ?bindings ?tmps ?body))))
219
220     ((let-values "mktmp" (?a . ?b) ?e0 (?arg ...) ?bindings (?tmp ...) ?body)
221      (let-values "mktmp" ?b ?e0 (?arg ... x) ?bindings (?tmp ... (?a x)) ?body))
222
223     ((let-values "mktmp" ?a ?e0 (?arg ...) ?bindings (?tmp ...) ?body)
224      (call-with-values
225        (lambda () ?e0)
226        (lambda (?arg ... . x)
227          (let-values "bind" ?bindings (?tmp ... (?a x)) ?body))))))
228
229 (define-syntax switch
230   (syntax-rules (else)
231     ((_ v (else e1 e2 ...))
232      (begin e1 e2 ...))
233     ((_ v (k e1 e2 ...))
234      (let ((x v))
235        (if (eqv? x k) (begin e1 e2 ...))))
236     ((_ v (k e1 e2 ...) c1 c2 ...)
237      (let ((x v))
238        (if (eqv? x k)
239      (begin e1 e2 ...)
240      (switch x c1 c2 ...))))))
241
242 (define-syntax optional
243   (syntax-rules ()
244     ((_ rest default)
245      (let ((tmp rest))
246        (cond ((null? tmp) default)
247        ((null? (cdr tmp)) (car tmp))
248        (else (##core#check (##sys#error (##core#immutable '"too many optional arguments") tmp))))))))
249
250 (define-syntax :optional    ; DEPRECATED
251   (syntax-rules ()
252     ((_ . rest) (optional . rest))))
253
254 (define-syntax let-optionals*
255   (syntax-rules ()
256     ((_ rest () body ...) (let () body ...))
257     ((_ rest ((var default) . more) body ...)
258      (let* ((tmp rest)
259       (var (if (null? tmp) default (car tmp)))
260       (rest2 (if (null? tmp) '() (cdr tmp))))
261        (let-optionals* rest2 more body ...)))
262     ((_ rest (var) body ...) (let ((var rest)) body ...))))
263
264 ;; Just generates temp variables for let-optionals*
265 ;; then binds them in one application, faster than
266 ;; Shiver's let-optionals.
267
268 (define-syntax let-optionals
269  (syntax-rules ()
270    ((let-optionals ("step") rest (tmps ...) ((var default) . vars) body)
271     (let-optionals ("step") rest (tmps ... (var tmp default)) vars body))
272    ((let-optionals ("step") rest ((var tmp default) ...) () body)
273     (let-optionals* rest ((tmp default) ...)
274       (let ((var tmp) ...)
275         body)))
276    ((let-optionals rest vars body ...)
277     (let-optionals ("step") rest () vars (begin body ...)))))
278
279 (define-syntax define-inline
280   (syntax-rules ()
281     ((_ head . body)
282      (define head . body))))
283
284 (define-syntax define-constant
285   (syntax-rules ()
286     ((_ name val) (define name val))))
287
288 (define-syntax critical-section
289   (syntax-rules ()
290     ((_ body ...)
291      (##sys#dynamic-wind
292    ##sys#disable-interrupts
293    (lambda () body ...)
294    ##sys#enable-interrupts))))
295
296 (define-syntax nth-value
297   (syntax-rules ()
298     ((_ i exp)
299      (##sys#call-with-values
300       (lambda () exp)
301       (lambda lst (list-ref lst i))))))
302
303 (define-syntax define-record-printer
304   (syntax-rules ()
305     ((_ (name var1 var2) body ...)
306      (##sys#register-record-printer 'name (lambda (var1 var2) body ...)))
307     ((_ name proc) (##sys#register-record-printer 'name proc))))
308
309 (define-syntax handle-exceptions
310   (syntax-rules ()
311     ((_ var handle-body e1 e2 ...)     
312      ((call-with-current-continuation
313        (lambda (k)
314    (with-exception-handler
315     (lambda (var) (k (lambda () handle-body)))
316     (lambda ()
317       (##sys#call-with-values
318        (lambda () e1 e2 ...)
319        (lambda args (k (lambda () (##sys#apply ##sys#values args)))))))))))))
320
321 (define-syntax condition-case
322   (syntax-rules ()
323     ((_ "1" exvar kvar) (##sys#signal exvar))
324     ((_ "1" exvar kvar (() body ...) . more) (let () body ...))
325     ((_ "1" exvar kvar (var () body ...) . more) (let ((var exvar)) body ...))
326     ((_ "1" exvar kvar ((kind ...) body ...) . more)
327      (if (and kvar (memv 'kind kvar) ...)
328    (let () body ...)
329    (condition-case "1" exvar kvar . more)))
330     ((_ "1" exvar kvar (var (kind ...) body ...) . more)
331      (if (and kvar (memv 'kind kvar) ...)
332    (let ((var exvar)) body ...)
333    (condition-case "1" exvar kvar . more)))
334     ((_ exp clauses ...)
335      (handle-exceptions exvar
336    (let ((kvar (and (##sys#structure? exvar 'condition) (##sys#slot exvar 1))))
337      (condition-case "1" exvar kvar clauses ...))
338        exp))))
339
340 (define-syntax define-class
341   (syntax-rules ()
342     ((_ name () slots)
343      (define-class name (<object>) slots))
344     ((_ name supers slots)
345      (define-class name supers slots <class>))
346     ((_ name () slots meta)
347      (define-class name (<object>) slots meta))
348     ((_ cname (supers ...) (slots ...) meta)
349      (define cname (make meta 'name 'cname 'direct-supers (list supers ...) 'direct-slots (list 'slots ...))))))
350
351 (define-syntax define-generic
352   (syntax-rules ()
353     ((_ n class) (define n (make class 'name 'n)))
354     ((_ n) (define n (make-generic 'n)))))
355
356 (define-syntax require-for-syntax
357   (syntax-rules ()
358     ((_ names ...)
359      (##core#require-for-syntax names ...))))
360
361 (define-syntax require-extension
362   (syntax-rules ()
363     ((_ names ...) (##core#require-extension 'names ...))))
364
365 (define-syntax use require-extension)
366
367 (define-syntax cut
368   (syntax-rules (<> <...>)
369
370     ;; construct fixed- or variable-arity procedure:
371     ;;   (begin proc) throws an error if proc is not an <expression>
372     ((_ "1" (slot-name ...) (proc arg ...))
373      (lambda (slot-name ...) ((begin proc) arg ...)))
374     ((_ "1" (slot-name ...) (proc arg ...) <...>)
375      (lambda (slot-name ... . rest-slot) (apply proc arg ... rest-slot)))
376
377     ;; process one slot-or-expr
378     ((_ "1" (slot-name ...)   (position ...)      <>  . se)
379      (cut "1" (slot-name ... x) (position ... x)        . se))
380     ((_ "1" (slot-name ...)   (position ...)      nse . se)
381      (cut "1" (slot-name ...)   (position ... nse)      . se))
382
383     ((_ . slots-or-exprs)
384      (cut "1" () () . slots-or-exprs))))
385
386 (define-syntax cute
387   (syntax-rules (<> <...>)
388
389     ;; If there are no slot-or-exprs to process, then:
390     ;; construct a fixed-arity procedure,
391     ((_ "1"
392       (slot-name ...) nse-bindings (proc arg ...))
393      (let nse-bindings (lambda (slot-name ...) (proc arg ...))))
394     ;; or a variable-arity procedure
395     ((_ "1"
396       (slot-name ...) nse-bindings (proc arg ...) <...>)
397      (let nse-bindings (lambda (slot-name ... . x) (apply proc arg ... x))))
398
399     ;; otherwise, process one slot:
400     ((_ "1"
401       (slot-name ...)         nse-bindings  (position ...)   <>  . se)
402      (cute "1"
403       (slot-name ... x)       nse-bindings  (position ... x)     . se))
404     ;; or one non-slot expression
405     ((_ "1"
406       slot-names              nse-bindings  (position ...)   nse . se)
407      (cute "1"
408       slot-names ((x nse) . nse-bindings) (position ... x)       . se))
409
410     ((cute . slots-or-exprs)
411      (cute "1" () () () . slots-or-exprs))))
412
413 (define-syntax let-string-start+end
414   (syntax-rules ()
415     ((let-string-start+end (start end) proc s-exp args-exp body ...)
416      (receive (start end) (string-parse-final-start+end proc s-exp args-exp)
417        body ...))
418     ((let-string-start+end (start end rest) proc s-exp args-exp body ...)
419      (receive (rest start end) (string-parse-start+end proc s-exp args-exp)
420        body ...))))
421
422 (define-syntax rec
423   (syntax-rules ()
424     ((rec (NAME . VARIABLES) . BODY)
425      (letrec ( (NAME (lambda VARIABLES . BODY))) NAME))
426     ((rec NAME EXPRESSION)
427      (letrec ( (NAME EXPRESSION)) NAME))))
428
429 (define-syntax define-record
430   (sc-macro-transformer
431    (lambda (form env)
432      (define (identifier->string x)
433        (symbol->string (identifier->symbol x)))
434      (define construct-name
435        (lambda (prefix . args)
436    (##sys#string->qualified-symbol
437     prefix
438     (##sys#apply string-append
439            (map (lambda (x) (if (string? x) x (identifier->string x)))
440           args)))))
441      (syntax-check '(keyword identifier * identifier) form)
442      (let* ((name (cadr form))
443       (slots (cddr form))
444       (setters (memq #:record-setters ##sys#features))
445       (prefix (##sys#qualified-symbol-prefix (identifier->symbol name))))
446        (capture-syntactic-environment
447   (lambda (xenv)
448     (define (close id)
449       (make-syntactic-closure xenv '() id))
450     `(begin
451        (define ,(construct-name prefix "make-" name)
452          (lambda ,slots (,(close '##sys#make-structure) ',name ,@slots)))
453        (define ,(construct-name prefix name "?")
454          (lambda (x) (##sys#structure? x ',name)))
455        ,@(let mapslots ((slots slots) (i 1))
456      (if (eq? slots '())
457          slots
458          (let* ((slotname (identifier->string (##sys#slot slots 0)))
459           (setr (construct-name prefix name "-" slotname "-set!"))
460           (getr (construct-name prefix name "-" slotname)))
461            (cons
462       `(begin
463          (define ,setr
464            (lambda (x val)
465              (##core#check (##sys#check-structure x ',name))
466              (##sys#block-set! x ,i val)))
467          (define ,getr
468            ,(if setters
469           `(getter-with-setter
470             (lambda (x)
471               (##core#check (##sys#check-structure x ',name))
472               (##sys#block-ref x ,i))
473             ,setr)
474           `(lambda (x)
475              (##core#check (##sys#check-structure x ',name))
476              (##sys#block-ref x ,i)))))
477       (mapslots (##sys#slot slots 1) (fx+ i 1)))))))))))))
478
479 ;; syntactic-closures uses letrec semantics for internal defines, so we
480 ;; have to defer any getter-with-setter calls until the end of the body.
481 (define-syntax define-record-type
482   (sc-macro-transformer
483    (lambda (form env)
484      (define (memi id ids)
485        (and (not (null? ids))
486       (or (identifier=? env id env (car ids))
487     (memi id (cdr ids)))))
488      (define (close id)
489        (make-syntactic-closure env '() id))
490      (syntax-check '(keyword identifier (+ identifier)
491            identifier * (+ identifier)) form)
492      (let ((t (cadr form))
493      (conser (caddr form))
494      (pred (cadddr form))
495      (slots (cddddr form)))
496        (let ((vars (cdr conser))
497        (slotnames (map car slots))
498              (setters? (memq #:record-setters ##sys#features)))
499
500    `(begin
501       (define ,conser
502         (##sys#make-structure
503          ',t
504          ,@(map (lambda (sname)
505       (if (memi sname vars)
506           sname
507           '(##sys#void)))
508           slotnames)))
509       (define (,pred x) (##sys#structure? x ',t))
510       ,@(let loop ((slots slots) (i 1) (deferred-sets '()))
511     (if (null? slots)
512         deferred-sets
513         (let* ((slot (car slots))
514          (get (cadr slot))
515          (set (and (pair? (cddr slot)) (caddr slot)))
516          (getr `(lambda (x)
517             (##core#check (##sys#check-structure x ',t))
518             (##sys#block-ref x ,i)))
519          (get/set (and set setters?
520            `(set! ,(close get)
521             (getter-with-setter ,getr ,(close set))))))
522           `(,@(if set
523             `((define (,set x y)
524           (##core#check (##sys#check-structure x ',t))
525           (##sys#block-set! x ,i y)))
526             '())
527       (define ,get ,(if get/set (##sys#void) getr))
528       ,@(loop (cdr slots) (add1 i)
529         (if get/set
530             (cons get/set deferred-sets)
531             deferred-sets))))))))))))
532
533 (define-syntax define-extension
534   (sc-macro-transformer
535    (lambda (form env)
536      (syntax-check '(keyword identifier * (identifier * expression)) form)
537      (capture-syntactic-environment
538       (lambda (xenv)
539   (define (literal=? usage-id transformer-id)
540     (and (identifier? usage-id)
541          (identifier=? env usage-id xenv transformer-id)))
542   (define (close expr)
543     (make-syntactic-closure env '() expr))
544
545   (let ((name (identifier->symbol (cadr form)))
546         (clauses (cddr form)))
547    (let loop ((s '()) (d '()) (cs clauses) (exports #f))
548      (if (null? cs)
549          (let ((exps (if exports `(declare (export ,@(map close exports))) '(begin))))
550      `(cond-expand
551        (chicken-compile-shared ,exps ,@d)
552        ((not compiling) ,@d)
553        (else
554         (declare (unit ,name))
555         ,exps
556         (provide ',name)
557         ,@s)))
558          (let ((t (caar cs))
559          (next (cdr cs)))
560      (cond ((literal=? t 'static)  (loop (cons `(begin ,@(map close (cdar cs))) s) d next exports))
561            ((literal=? t 'dynamic) (loop s (cons `(begin ,@(map close (cdar cs))) d) next exports))
562            ((literal=? t 'export)  (loop s d next (append (or exports '()) (cdar cs))))
563            (else (syntax-error 'define-extension "invalid clause specifier" t))))))))))))
564
565 (define-macro (define-for-syntax head . body)
566   (let* ((body (if (null? body) '((void)) body))
567    (name (if (pair? head) (car head) head))
568    (body (if (pair? head) `(lambda ,(cdr head) ,@body) (car body))))
569     (if (symbol? name)
570   (##sys#setslot name 0 (eval body))
571   (syntax-error 'define-for-syntax "invalid identifier" name))
572     (if ##sys#enable-runtime-macros
573   `(define ,name ,body)
574   '(begin))))
575
576 (define-syntax fluid-let
577   (syntax-rules ()
578     ((_ ((v1 e1) ...) b1 b2 ...)
579      (fluid-let "temps" () ((v1 e1) ...) b1 b2 ...))
580     ((_ "temps" (t ...) ((v1 e1) x ...) b1 b2 ...)
581      (let ((temp e1))
582        (fluid-let "temps" ((temp e1 v1) t ...) (x ...) b1 b2 ...)))
583     ((_ "temps" ((t e v) ...) () b1 b2 ...)
584      (let-syntax ((swap!
585                    (syntax-rules ()
586                      ((swap! a b)
587                       (let ((tmp a))
588                         (set! a b)
589                         (set! b tmp))))))
590        (dynamic-wind
591         (lambda ()
592           (swap! t v) ...)
593         (lambda ()
594           b1 b2 ...)
595         (lambda ()
596           (swap! t v) ...))))))
597
Note: See TracBrowser for help on using the browser.