Merge remote-tracking branch 'origin/stable-2.0'
[bpt/guile.git] / module / ice-9 / psyntax.scm
1 ;;;; -*-scheme-*-
2 ;;;;
3 ;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011,
4 ;;;; 2012, 2013 Free Software Foundation, Inc.
5 ;;;;
6 ;;;; This library is free software; you can redistribute it and/or
7 ;;;; modify it under the terms of the GNU Lesser General Public
8 ;;;; License as published by the Free Software Foundation; either
9 ;;;; version 3 of the License, or (at your option) any later version.
10 ;;;;
11 ;;;; This library is distributed in the hope that it will be useful,
12 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ;;;; Lesser General Public License for more details.
15 ;;;;
16 ;;;; You should have received a copy of the GNU Lesser General Public
17 ;;;; License along with this library; if not, write to the Free Software
18 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 ;;;;
20 \f
21
22 ;;; Portable implementation of syntax-case
23 ;;; Originally extracted from Chez Scheme Version 5.9f
24 ;;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman
25
26 ;;; Copyright (c) 1992-1997 Cadence Research Systems
27 ;;; Permission to copy this software, in whole or in part, to use this
28 ;;; software for any lawful purpose, and to redistribute this software
29 ;;; is granted subject to the restriction that all copies made of this
30 ;;; software must include this copyright notice in full. This software
31 ;;; is provided AS IS, with NO WARRANTY, EITHER EXPRESS OR IMPLIED,
32 ;;; INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
33 ;;; OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE
34 ;;; AUTHORS BE LIABLE FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES OF ANY
35 ;;; NATURE WHATSOEVER.
36
37 ;;; Modified by Mikael Djurfeldt <djurfeldt@nada.kth.se> according
38 ;;; to the ChangeLog distributed in the same directory as this file:
39 ;;; 1997-08-19, 1997-09-03, 1997-09-10, 2000-08-13, 2000-08-24,
40 ;;; 2000-09-12, 2001-03-08
41
42 ;;; Modified by Andy Wingo <wingo@pobox.com> according to the Git
43 ;;; revision control logs corresponding to this file: 2009, 2010.
44
45
46 ;;; This code is based on "Syntax Abstraction in Scheme"
47 ;;; by R. Kent Dybvig, Robert Hieb, and Carl Bruggeman.
48 ;;; Lisp and Symbolic Computation 5:4, 295-326, 1992.
49 ;;; <http://www.cs.indiana.edu/~dyb/pubs/LaSC-5-4-pp295-326.pdf>
50
51
52 ;;; This file defines the syntax-case expander, macroexpand, and a set
53 ;;; of associated syntactic forms and procedures. Of these, the
54 ;;; following are documented in The Scheme Programming Language,
55 ;;; Fourth Edition (R. Kent Dybvig, MIT Press, 2009), and in the
56 ;;; R6RS:
57 ;;;
58 ;;; bound-identifier=?
59 ;;; datum->syntax
60 ;;; define-syntax
61 ;;; syntax-parameterize
62 ;;; free-identifier=?
63 ;;; generate-temporaries
64 ;;; identifier?
65 ;;; identifier-syntax
66 ;;; let-syntax
67 ;;; letrec-syntax
68 ;;; syntax
69 ;;; syntax-case
70 ;;; syntax->datum
71 ;;; syntax-rules
72 ;;; with-syntax
73 ;;;
74 ;;; Additionally, the expander provides definitions for a number of core
75 ;;; Scheme syntactic bindings, such as `let', `lambda', and the like.
76
77 ;;; The remaining exports are listed below:
78 ;;;
79 ;;; (macroexpand datum)
80 ;;; if datum represents a valid expression, macroexpand returns an
81 ;;; expanded version of datum in a core language that includes no
82 ;;; syntactic abstractions. The core language includes begin,
83 ;;; define, if, lambda, letrec, quote, and set!.
84 ;;; (eval-when situations expr ...)
85 ;;; conditionally evaluates expr ... at compile-time or run-time
86 ;;; depending upon situations (see the Chez Scheme System Manual,
87 ;;; Revision 3, for a complete description)
88 ;;; (syntax-violation who message form [subform])
89 ;;; used to report errors found during expansion
90 ;;; ($sc-dispatch e p)
91 ;;; used by expanded code to handle syntax-case matching
92
93 ;;; This file is shipped along with an expanded version of itself,
94 ;;; psyntax-pp.scm, which is loaded when psyntax.scm has not yet been
95 ;;; compiled. In this way, psyntax bootstraps off of an expanded
96 ;;; version of itself.
97
98 ;;; This implementation of the expander sometimes uses syntactic
99 ;;; abstractions when procedural abstractions would suffice. For
100 ;;; example, we define top-wrap and top-marked? as
101 ;;;
102 ;;; (define-syntax top-wrap (identifier-syntax '((top))))
103 ;;; (define-syntax top-marked?
104 ;;; (syntax-rules ()
105 ;;; ((_ w) (memq 'top (wrap-marks w)))))
106 ;;;
107 ;;; rather than
108 ;;;
109 ;;; (define top-wrap '((top)))
110 ;;; (define top-marked?
111 ;;; (lambda (w) (memq 'top (wrap-marks w))))
112 ;;;
113 ;;; On the other hand, we don't do this consistently; we define
114 ;;; make-wrap, wrap-marks, and wrap-subst simply as
115 ;;;
116 ;;; (define make-wrap cons)
117 ;;; (define wrap-marks car)
118 ;;; (define wrap-subst cdr)
119 ;;;
120 ;;; In Chez Scheme, the syntactic and procedural forms of these
121 ;;; abstractions are equivalent, since the optimizer consistently
122 ;;; integrates constants and small procedures. This will be true of
123 ;;; Guile as well, once we implement a proper inliner.
124
125
126 ;;; Implementation notes:
127
128 ;;; Objects with no standard print syntax, including objects containing
129 ;;; cycles and syntax object, are allowed in quoted data as long as they
130 ;;; are contained within a syntax form or produced by datum->syntax.
131 ;;; Such objects are never copied.
132
133 ;;; All identifiers that don't have macro definitions and are not bound
134 ;;; lexically are assumed to be global variables.
135
136 ;;; Top-level definitions of macro-introduced identifiers are allowed.
137 ;;; This may not be appropriate for implementations in which the
138 ;;; model is that bindings are created by definitions, as opposed to
139 ;;; one in which initial values are assigned by definitions.
140
141 ;;; Identifiers and syntax objects are implemented as vectors for
142 ;;; portability. As a result, it is possible to "forge" syntax objects.
143
144 ;;; The implementation of generate-temporaries assumes that it is
145 ;;; possible to generate globally unique symbols (gensyms).
146
147 ;;; The source location associated with incoming expressions is tracked
148 ;;; via the source-properties mechanism, a weak map from expression to
149 ;;; source information. At times the source is separated from the
150 ;;; expression; see the note below about "efficiency and confusion".
151
152
153 ;;; Bootstrapping:
154
155 ;;; When changing syntax-object representations, it is necessary to support
156 ;;; both old and new syntax-object representations in id-var-name. It
157 ;;; should be sufficient to recognize old representations and treat
158 ;;; them as not lexically bound.
159
160
161
162 (eval-when (compile)
163 (set-current-module (resolve-module '(guile))))
164
165 (let ()
166 (define-syntax define-expansion-constructors
167 (lambda (x)
168 (syntax-case x ()
169 ((_)
170 (let lp ((n 0) (out '()))
171 (if (< n (vector-length %expanded-vtables))
172 (lp (1+ n)
173 (let* ((vtable (vector-ref %expanded-vtables n))
174 (stem (struct-ref vtable (+ vtable-offset-user 0)))
175 (fields (struct-ref vtable (+ vtable-offset-user 2)))
176 (sfields (map (lambda (f) (datum->syntax x f)) fields))
177 (ctor (datum->syntax x (symbol-append 'make- stem))))
178 (cons #`(define (#,ctor #,@sfields)
179 (make-struct (vector-ref %expanded-vtables #,n) 0
180 #,@sfields))
181 out)))
182 #`(begin #,@(reverse out))))))))
183
184 (define-syntax define-expansion-accessors
185 (lambda (x)
186 (syntax-case x ()
187 ((_ stem field ...)
188 (let lp ((n 0))
189 (let ((vtable (vector-ref %expanded-vtables n))
190 (stem (syntax->datum #'stem)))
191 (if (eq? (struct-ref vtable (+ vtable-offset-user 0)) stem)
192 #`(begin
193 (define (#,(datum->syntax x (symbol-append stem '?)) x)
194 (and (struct? x)
195 (eq? (struct-vtable x)
196 (vector-ref %expanded-vtables #,n))))
197 #,@(map
198 (lambda (f)
199 (let ((get (datum->syntax x (symbol-append stem '- f)))
200 (set (datum->syntax x (symbol-append 'set- stem '- f '!)))
201 (idx (list-index (struct-ref vtable
202 (+ vtable-offset-user 2))
203 f)))
204 #`(begin
205 (define (#,get x)
206 (struct-ref x #,idx))
207 (define (#,set x v)
208 (struct-set! x #,idx v)))))
209 (syntax->datum #'(field ...))))
210 (lp (1+ n)))))))))
211
212 (define-syntax define-structure
213 (lambda (x)
214 (define construct-name
215 (lambda (template-identifier . args)
216 (datum->syntax
217 template-identifier
218 (string->symbol
219 (apply string-append
220 (map (lambda (x)
221 (if (string? x)
222 x
223 (symbol->string (syntax->datum x))))
224 args))))))
225 (syntax-case x ()
226 ((_ (name id1 ...))
227 (and-map identifier? #'(name id1 ...))
228 (with-syntax
229 ((constructor (construct-name #'name "make-" #'name))
230 (predicate (construct-name #'name #'name "?"))
231 ((access ...)
232 (map (lambda (x) (construct-name x #'name "-" x))
233 #'(id1 ...)))
234 ((assign ...)
235 (map (lambda (x)
236 (construct-name x "set-" #'name "-" x "!"))
237 #'(id1 ...)))
238 (structure-length
239 (+ (length #'(id1 ...)) 1))
240 ((index ...)
241 (let f ((i 1) (ids #'(id1 ...)))
242 (if (null? ids)
243 '()
244 (cons i (f (+ i 1) (cdr ids)))))))
245 #'(begin
246 (define constructor
247 (lambda (id1 ...)
248 (vector 'name id1 ... )))
249 (define predicate
250 (lambda (x)
251 (and (vector? x)
252 (= (vector-length x) structure-length)
253 (eq? (vector-ref x 0) 'name))))
254 (define access
255 (lambda (x)
256 (vector-ref x index)))
257 ...
258 (define assign
259 (lambda (x update)
260 (vector-set! x index update)))
261 ...))))))
262
263 (let ()
264 (define-expansion-constructors)
265 (define-expansion-accessors lambda meta)
266
267 ;; hooks to nonportable run-time helpers
268 (begin
269 (define-syntax fx+ (identifier-syntax +))
270 (define-syntax fx- (identifier-syntax -))
271 (define-syntax fx= (identifier-syntax =))
272 (define-syntax fx< (identifier-syntax <))
273
274 (define top-level-eval-hook
275 (lambda (x mod)
276 (primitive-eval x)))
277
278 (define local-eval-hook
279 (lambda (x mod)
280 (primitive-eval x)))
281
282 ;; Capture syntax-session-id before we shove it off into a module.
283 (define session-id
284 (let ((v (module-variable (current-module) 'syntax-session-id)))
285 (lambda ()
286 ((variable-ref v)))))
287
288 (define put-global-definition-hook
289 (lambda (symbol type val)
290 (module-define! (current-module)
291 symbol
292 (make-syntax-transformer symbol type val))))
293
294 (define get-global-definition-hook
295 (lambda (symbol module)
296 (if (and (not module) (current-module))
297 (warn "module system is booted, we should have a module" symbol))
298 (and (not (equal? module '(primitive)))
299 (let ((v (module-variable (if module
300 (resolve-module (cdr module))
301 (current-module))
302 symbol)))
303 (and v (variable-bound? v)
304 (let ((val (variable-ref v)))
305 (and (macro? val) (macro-type val)
306 (cons (macro-type val)
307 (macro-binding val))))))))))
308
309
310 (define (decorate-source e s)
311 (if (and s (supports-source-properties? e))
312 (set-source-properties! e s))
313 e)
314
315 (define (maybe-name-value! name val)
316 (if (lambda? val)
317 (let ((meta (lambda-meta val)))
318 (if (not (assq 'name meta))
319 (set-lambda-meta! val (acons 'name name meta))))))
320
321 ;; output constructors
322 (define build-void
323 (lambda (source)
324 (make-void source)))
325
326 (define build-call
327 (lambda (source fun-exp arg-exps)
328 (make-call source fun-exp arg-exps)))
329
330 (define build-conditional
331 (lambda (source test-exp then-exp else-exp)
332 (make-conditional source test-exp then-exp else-exp)))
333
334 (define build-lexical-reference
335 (lambda (type source name var)
336 (make-lexical-ref source name var)))
337
338 (define build-lexical-assignment
339 (lambda (source name var exp)
340 (maybe-name-value! name exp)
341 (make-lexical-set source name var exp)))
342
343 (define (analyze-variable mod var modref-cont bare-cont)
344 (if (not mod)
345 (bare-cont var)
346 (let ((kind (car mod))
347 (mod (cdr mod)))
348 (case kind
349 ((public) (modref-cont mod var #t))
350 ((private) (if (not (equal? mod (module-name (current-module))))
351 (modref-cont mod var #f)
352 (bare-cont var)))
353 ((bare) (bare-cont var))
354 ((hygiene) (if (and (not (equal? mod (module-name (current-module))))
355 (module-variable (resolve-module mod) var))
356 (modref-cont mod var #f)
357 (bare-cont var)))
358 ((primitive)
359 (syntax-violation #f "primitive not in operator position" var))
360 (else (syntax-violation #f "bad module kind" var mod))))))
361
362 (define build-global-reference
363 (lambda (source var mod)
364 (analyze-variable
365 mod var
366 (lambda (mod var public?)
367 (make-module-ref source mod var public?))
368 (lambda (var)
369 (make-toplevel-ref source var)))))
370
371 (define build-global-assignment
372 (lambda (source var exp mod)
373 (maybe-name-value! var exp)
374 (analyze-variable
375 mod var
376 (lambda (mod var public?)
377 (make-module-set source mod var public? exp))
378 (lambda (var)
379 (make-toplevel-set source var exp)))))
380
381 (define build-global-definition
382 (lambda (source var exp)
383 (maybe-name-value! var exp)
384 (make-toplevel-define source var exp)))
385
386 (define build-simple-lambda
387 (lambda (src req rest vars meta exp)
388 (make-lambda src
389 meta
390 ;; hah, a case in which kwargs would be nice.
391 (make-lambda-case
392 ;; src req opt rest kw inits vars body else
393 src req #f rest #f '() vars exp #f))))
394
395 (define build-case-lambda
396 (lambda (src meta body)
397 (make-lambda src meta body)))
398
399 (define build-lambda-case
400 ;; req := (name ...)
401 ;; opt := (name ...) | #f
402 ;; rest := name | #f
403 ;; kw := (allow-other-keys? (keyword name var) ...) | #f
404 ;; inits: (init ...)
405 ;; vars: (sym ...)
406 ;; vars map to named arguments in the following order:
407 ;; required, optional (positional), rest, keyword.
408 ;; the body of a lambda: anything, already expanded
409 ;; else: lambda-case | #f
410 (lambda (src req opt rest kw inits vars body else-case)
411 (make-lambda-case src req opt rest kw inits vars body else-case)))
412
413 (define build-primcall
414 (lambda (src name args)
415 (make-primcall src name args)))
416
417 (define build-primref
418 (lambda (src name)
419 (make-primitive-ref src name)))
420
421 (define (build-data src exp)
422 (make-const src exp))
423
424 (define build-sequence
425 (lambda (src exps)
426 (if (null? (cdr exps))
427 (car exps)
428 (make-seq src (car exps) (build-sequence #f (cdr exps))))))
429
430 (define build-let
431 (lambda (src ids vars val-exps body-exp)
432 (for-each maybe-name-value! ids val-exps)
433 (if (null? vars)
434 body-exp
435 (make-let src ids vars val-exps body-exp))))
436
437 (define build-named-let
438 (lambda (src ids vars val-exps body-exp)
439 (let ((f (car vars))
440 (f-name (car ids))
441 (vars (cdr vars))
442 (ids (cdr ids)))
443 (let ((proc (build-simple-lambda src ids #f vars '() body-exp)))
444 (maybe-name-value! f-name proc)
445 (for-each maybe-name-value! ids val-exps)
446 (make-letrec
447 src #f
448 (list f-name) (list f) (list proc)
449 (build-call src (build-lexical-reference 'fun src f-name f)
450 val-exps))))))
451
452 (define build-letrec
453 (lambda (src in-order? ids vars val-exps body-exp)
454 (if (null? vars)
455 body-exp
456 (begin
457 (for-each maybe-name-value! ids val-exps)
458 (make-letrec src in-order? ids vars val-exps body-exp)))))
459
460
461 ;; FIXME: use a faster gensym
462 (define-syntax-rule (build-lexical-var src id)
463 (gensym (string-append (symbol->string id) "-")))
464
465 (define-structure (syntax-object expression wrap module))
466
467 (define-syntax no-source (identifier-syntax #f))
468
469 (define source-annotation
470 (lambda (x)
471 (let ((props (source-properties
472 (if (syntax-object? x)
473 (syntax-object-expression x)
474 x))))
475 (and (pair? props) props))))
476
477 (define-syntax-rule (arg-check pred? e who)
478 (let ((x e))
479 (if (not (pred? x)) (syntax-violation who "invalid argument" x))))
480
481 ;; compile-time environments
482
483 ;; wrap and environment comprise two level mapping.
484 ;; wrap : id --> label
485 ;; env : label --> <element>
486
487 ;; environments are represented in two parts: a lexical part and a global
488 ;; part. The lexical part is a simple list of associations from labels
489 ;; to bindings. The global part is implemented by
490 ;; {put,get}-global-definition-hook and associates symbols with
491 ;; bindings.
492
493 ;; global (assumed global variable) and displaced-lexical (see below)
494 ;; do not show up in any environment; instead, they are fabricated by
495 ;; resolve-identifier when it finds no other bindings.
496
497 ;; <environment> ::= ((<label> . <binding>)*)
498
499 ;; identifier bindings include a type and a value
500
501 ;; <binding> ::= (macro . <procedure>) macros
502 ;; (syntax-parameter . (<procedure>)) syntax parameters
503 ;; (core . <procedure>) core forms
504 ;; (module-ref . <procedure>) @ or @@
505 ;; (begin) begin
506 ;; (define) define
507 ;; (define-syntax) define-syntax
508 ;; (define-syntax-parameter) define-syntax-parameter
509 ;; (local-syntax . rec?) let-syntax/letrec-syntax
510 ;; (eval-when) eval-when
511 ;; (syntax . (<var> . <level>)) pattern variables
512 ;; (global) assumed global variable
513 ;; (lexical . <var>) lexical variables
514 ;; (displaced-lexical) displaced lexicals
515 ;; <level> ::= <nonnegative integer>
516 ;; <var> ::= variable returned by build-lexical-var
517
518 ;; a macro is a user-defined syntactic-form. a core is a
519 ;; system-defined syntactic form. begin, define, define-syntax,
520 ;; define-syntax-parameter, and eval-when are treated specially
521 ;; since they are sensitive to whether the form is at top-level and
522 ;; (except for eval-when) can denote valid internal definitions.
523
524 ;; a pattern variable is a variable introduced by syntax-case and can
525 ;; be referenced only within a syntax form.
526
527 ;; any identifier for which no top-level syntax definition or local
528 ;; binding of any kind has been seen is assumed to be a global
529 ;; variable.
530
531 ;; a lexical variable is a lambda- or letrec-bound variable.
532
533 ;; a displaced-lexical identifier is a lexical identifier removed from
534 ;; it's scope by the return of a syntax object containing the identifier.
535 ;; a displaced lexical can also appear when a letrec-syntax-bound
536 ;; keyword is referenced on the rhs of one of the letrec-syntax clauses.
537 ;; a displaced lexical should never occur with properly written macros.
538
539 (define-syntax make-binding
540 (syntax-rules (quote)
541 ((_ type value) (cons type value))
542 ((_ 'type) '(type))
543 ((_ type) (cons type '()))))
544 (define-syntax-rule (binding-type x)
545 (car x))
546 (define-syntax-rule (binding-value x)
547 (cdr x))
548
549 (define-syntax null-env (identifier-syntax '()))
550
551 (define extend-env
552 (lambda (labels bindings r)
553 (if (null? labels)
554 r
555 (extend-env (cdr labels) (cdr bindings)
556 (cons (cons (car labels) (car bindings)) r)))))
557
558 (define extend-var-env
559 ;; variant of extend-env that forms "lexical" binding
560 (lambda (labels vars r)
561 (if (null? labels)
562 r
563 (extend-var-env (cdr labels) (cdr vars)
564 (cons (cons (car labels) (make-binding 'lexical (car vars))) r)))))
565
566 ;; we use a "macros only" environment in expansion of local macro
567 ;; definitions so that their definitions can use local macros without
568 ;; attempting to use other lexical identifiers.
569 (define macros-only-env
570 (lambda (r)
571 (if (null? r)
572 '()
573 (let ((a (car r)))
574 (if (memq (cadr a) '(macro syntax-parameter))
575 (cons a (macros-only-env (cdr r)))
576 (macros-only-env (cdr r)))))))
577
578 (define global-extend
579 (lambda (type sym val)
580 (put-global-definition-hook sym type val)))
581
582
583 ;; Conceptually, identifiers are always syntax objects. Internally,
584 ;; however, the wrap is sometimes maintained separately (a source of
585 ;; efficiency and confusion), so that symbols are also considered
586 ;; identifiers by id?. Externally, they are always wrapped.
587
588 (define nonsymbol-id?
589 (lambda (x)
590 (and (syntax-object? x)
591 (symbol? (syntax-object-expression x)))))
592
593 (define id?
594 (lambda (x)
595 (cond
596 ((symbol? x) #t)
597 ((syntax-object? x) (symbol? (syntax-object-expression x)))
598 (else #f))))
599
600 (define-syntax-rule (id-sym-name e)
601 (let ((x e))
602 (if (syntax-object? x)
603 (syntax-object-expression x)
604 x)))
605
606 (define id-sym-name&marks
607 (lambda (x w)
608 (if (syntax-object? x)
609 (values
610 (syntax-object-expression x)
611 (join-marks (wrap-marks w) (wrap-marks (syntax-object-wrap x))))
612 (values x (wrap-marks w)))))
613
614 ;; syntax object wraps
615
616 ;; <wrap> ::= ((<mark> ...) . (<subst> ...))
617 ;; <subst> ::= shift | <subs>
618 ;; <subs> ::= #(ribcage #(<sym> ...) #(<mark> ...) #(<label> ...))
619 ;; | #(ribcage (<sym> ...) (<mark> ...) (<label> ...))
620
621 (define-syntax make-wrap (identifier-syntax cons))
622 (define-syntax wrap-marks (identifier-syntax car))
623 (define-syntax wrap-subst (identifier-syntax cdr))
624
625 ;; labels must be comparable with "eq?", have read-write invariance,
626 ;; and distinct from symbols.
627 (define (gen-label)
628 (string-append "l-" (session-id) (symbol->string (gensym "-"))))
629
630 (define gen-labels
631 (lambda (ls)
632 (if (null? ls)
633 '()
634 (cons (gen-label) (gen-labels (cdr ls))))))
635
636 (define-structure (ribcage symnames marks labels))
637
638 (define-syntax empty-wrap (identifier-syntax '(())))
639
640 (define-syntax top-wrap (identifier-syntax '((top))))
641
642 (define-syntax-rule (top-marked? w)
643 (memq 'top (wrap-marks w)))
644
645 ;; Marks must be comparable with "eq?" and distinct from pairs and
646 ;; the symbol top. We do not use integers so that marks will remain
647 ;; unique even across file compiles.
648
649 (define-syntax the-anti-mark (identifier-syntax #f))
650
651 (define anti-mark
652 (lambda (w)
653 (make-wrap (cons the-anti-mark (wrap-marks w))
654 (cons 'shift (wrap-subst w)))))
655
656 (define-syntax-rule (new-mark)
657 (gensym (string-append "m-" (session-id) "-")))
658
659 ;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
660 ;; internal definitions, in which the ribcages are built incrementally
661 (define-syntax-rule (make-empty-ribcage)
662 (make-ribcage '() '() '()))
663
664 (define extend-ribcage!
665 ;; must receive ids with complete wraps
666 (lambda (ribcage id label)
667 (set-ribcage-symnames! ribcage
668 (cons (syntax-object-expression id)
669 (ribcage-symnames ribcage)))
670 (set-ribcage-marks! ribcage
671 (cons (wrap-marks (syntax-object-wrap id))
672 (ribcage-marks ribcage)))
673 (set-ribcage-labels! ribcage
674 (cons label (ribcage-labels ribcage)))))
675
676 ;; make-binding-wrap creates vector-based ribcages
677 (define make-binding-wrap
678 (lambda (ids labels w)
679 (if (null? ids)
680 w
681 (make-wrap
682 (wrap-marks w)
683 (cons
684 (let ((labelvec (list->vector labels)))
685 (let ((n (vector-length labelvec)))
686 (let ((symnamevec (make-vector n)) (marksvec (make-vector n)))
687 (let f ((ids ids) (i 0))
688 (if (not (null? ids))
689 (call-with-values
690 (lambda () (id-sym-name&marks (car ids) w))
691 (lambda (symname marks)
692 (vector-set! symnamevec i symname)
693 (vector-set! marksvec i marks)
694 (f (cdr ids) (fx+ i 1))))))
695 (make-ribcage symnamevec marksvec labelvec))))
696 (wrap-subst w))))))
697
698 (define smart-append
699 (lambda (m1 m2)
700 (if (null? m2)
701 m1
702 (append m1 m2))))
703
704 (define join-wraps
705 (lambda (w1 w2)
706 (let ((m1 (wrap-marks w1)) (s1 (wrap-subst w1)))
707 (if (null? m1)
708 (if (null? s1)
709 w2
710 (make-wrap
711 (wrap-marks w2)
712 (smart-append s1 (wrap-subst w2))))
713 (make-wrap
714 (smart-append m1 (wrap-marks w2))
715 (smart-append s1 (wrap-subst w2)))))))
716
717 (define join-marks
718 (lambda (m1 m2)
719 (smart-append m1 m2)))
720
721 (define same-marks?
722 (lambda (x y)
723 (or (eq? x y)
724 (and (not (null? x))
725 (not (null? y))
726 (eq? (car x) (car y))
727 (same-marks? (cdr x) (cdr y))))))
728
729 (define id-var-name
730 ;; Syntax objects use wraps to associate names with marked
731 ;; identifiers. This function returns the name corresponding to
732 ;; the given identifier and wrap, or the original identifier if no
733 ;; corresponding name was found.
734 ;;
735 ;; The name may be a string created by gen-label, indicating a
736 ;; lexical binding, or another syntax object, indicating a
737 ;; reference to a top-level definition created during a previous
738 ;; macroexpansion.
739 ;;
740 ;; For lexical variables, finding a label simply amounts to
741 ;; looking for an entry with the same symbolic name and the same
742 ;; marks. Finding a toplevel definition is the same, except we
743 ;; also have to compare modules, hence the `mod' parameter.
744 ;; Instead of adding a separate entry in the ribcage for modules,
745 ;; which wouldn't be used for lexicals, we arrange for the entry
746 ;; for the name entry to be a pair with the module in its car, and
747 ;; the name itself in the cdr. So if the name that we find is a
748 ;; pair, we have to check modules.
749 ;;
750 ;; The identifer may be passed in wrapped or unwrapped. In any
751 ;; case, this routine returns either a symbol, a syntax object, or
752 ;; a string label.
753 ;;
754 (lambda (id w mod)
755 (define-syntax-rule (first e)
756 ;; Rely on Guile's multiple-values truncation.
757 e)
758 (define search
759 (lambda (sym subst marks mod)
760 (if (null? subst)
761 (values #f marks)
762 (let ((fst (car subst)))
763 (if (eq? fst 'shift)
764 (search sym (cdr subst) (cdr marks) mod)
765 (let ((symnames (ribcage-symnames fst)))
766 (if (vector? symnames)
767 (search-vector-rib sym subst marks symnames fst mod)
768 (search-list-rib sym subst marks symnames fst mod))))))))
769 (define search-list-rib
770 (lambda (sym subst marks symnames ribcage mod)
771 (let f ((symnames symnames) (i 0))
772 (cond
773 ((null? symnames) (search sym (cdr subst) marks mod))
774 ((and (eq? (car symnames) sym)
775 (same-marks? marks (list-ref (ribcage-marks ribcage) i)))
776 (let ((n (list-ref (ribcage-labels ribcage) i)))
777 (if (pair? n)
778 (if (equal? mod (car n))
779 (values (cdr n) marks)
780 (f (cdr symnames) (fx+ i 1)))
781 (values n marks))))
782 (else (f (cdr symnames) (fx+ i 1)))))))
783 (define search-vector-rib
784 (lambda (sym subst marks symnames ribcage mod)
785 (let ((n (vector-length symnames)))
786 (let f ((i 0))
787 (cond
788 ((fx= i n) (search sym (cdr subst) marks mod))
789 ((and (eq? (vector-ref symnames i) sym)
790 (same-marks? marks (vector-ref (ribcage-marks ribcage) i)))
791 (let ((n (vector-ref (ribcage-labels ribcage) i)))
792 (if (pair? n)
793 (if (equal? mod (car n))
794 (values (cdr n) marks)
795 (f (fx+ i 1)))
796 (values n marks))))
797 (else (f (fx+ i 1))))))))
798 (cond
799 ((symbol? id)
800 (or (first (search id (wrap-subst w) (wrap-marks w) mod)) id))
801 ((syntax-object? id)
802 (let ((id (syntax-object-expression id))
803 (w1 (syntax-object-wrap id))
804 (mod (syntax-object-module id)))
805 (let ((marks (join-marks (wrap-marks w) (wrap-marks w1))))
806 (call-with-values (lambda () (search id (wrap-subst w) marks mod))
807 (lambda (new-id marks)
808 (or new-id
809 (first (search id (wrap-subst w1) marks mod))
810 id))))))
811 (else (syntax-violation 'id-var-name "invalid id" id)))))
812
813 ;; A helper procedure for syntax-locally-bound-identifiers, which
814 ;; itself is a helper for transformer procedures.
815 ;; `locally-bound-identifiers' returns a list of all bindings
816 ;; visible to a syntax object with the given wrap. They are in
817 ;; order from outer to inner.
818 ;;
819 ;; The purpose of this procedure is to give a transformer procedure
820 ;; references on bound identifiers, that the transformer can then
821 ;; introduce some of them in its output. As such, the identifiers
822 ;; are anti-marked, so that rebuild-macro-output doesn't apply new
823 ;; marks to them.
824 ;;
825 (define locally-bound-identifiers
826 (lambda (w mod)
827 (define scan
828 (lambda (subst results)
829 (if (null? subst)
830 results
831 (let ((fst (car subst)))
832 (if (eq? fst 'shift)
833 (scan (cdr subst) results)
834 (let ((symnames (ribcage-symnames fst))
835 (marks (ribcage-marks fst)))
836 (if (vector? symnames)
837 (scan-vector-rib subst symnames marks results)
838 (scan-list-rib subst symnames marks results))))))))
839 (define scan-list-rib
840 (lambda (subst symnames marks results)
841 (let f ((symnames symnames) (marks marks) (results results))
842 (if (null? symnames)
843 (scan (cdr subst) results)
844 (f (cdr symnames) (cdr marks)
845 (cons (wrap (car symnames)
846 (anti-mark (make-wrap (car marks) subst))
847 mod)
848 results))))))
849 (define scan-vector-rib
850 (lambda (subst symnames marks results)
851 (let ((n (vector-length symnames)))
852 (let f ((i 0) (results results))
853 (if (fx= i n)
854 (scan (cdr subst) results)
855 (f (fx+ i 1)
856 (cons (wrap (vector-ref symnames i)
857 (anti-mark (make-wrap (vector-ref marks i) subst))
858 mod)
859 results)))))))
860 (scan (wrap-subst w) '())))
861
862 ;; Returns three values: binding type, binding value, the module (for
863 ;; resolving toplevel vars).
864 (define (resolve-identifier id w r mod resolve-syntax-parameters?)
865 (define (resolve-syntax-parameters b)
866 (if (and resolve-syntax-parameters?
867 (eq? (binding-type b) 'syntax-parameter))
868 (or (assq-ref r (binding-value b))
869 (make-binding 'macro (car (binding-value b))))
870 b))
871 (define (resolve-global var mod)
872 (let ((b (resolve-syntax-parameters
873 (or (get-global-definition-hook var mod)
874 (make-binding 'global)))))
875 (if (eq? (binding-type b) 'global)
876 (values 'global var mod)
877 (values (binding-type b) (binding-value b) mod))))
878 (define (resolve-lexical label mod)
879 (let ((b (resolve-syntax-parameters
880 (or (assq-ref r label)
881 (make-binding 'displaced-lexical)))))
882 (values (binding-type b) (binding-value b) mod)))
883 (let ((n (id-var-name id w mod)))
884 (cond
885 ((syntax-object? n)
886 ;; Recursing allows syntax-parameterize to override
887 ;; macro-introduced syntax parameters.
888 (resolve-identifier n w r mod resolve-syntax-parameters?))
889 ((symbol? n)
890 (resolve-global n (if (syntax-object? id)
891 (syntax-object-module id)
892 mod)))
893 ((string? n)
894 (resolve-lexical n (if (syntax-object? id)
895 (syntax-object-module id)
896 mod)))
897 (else
898 (error "unexpected id-var-name" id w n)))))
899
900 (define transformer-environment
901 (make-fluid
902 (lambda (k)
903 (error "called outside the dynamic extent of a syntax transformer"))))
904
905 (define (with-transformer-environment k)
906 ((fluid-ref transformer-environment) k))
907
908 ;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
909 ;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
910
911 (define free-id=?
912 (lambda (i j)
913 (let* ((mi (and (syntax-object? i) (syntax-object-module i)))
914 (mj (and (syntax-object? j) (syntax-object-module j)))
915 (ni (id-var-name i empty-wrap mi))
916 (nj (id-var-name j empty-wrap mj)))
917 (define (id-module-binding id mod)
918 (module-variable
919 (if mod
920 ;; The normal case.
921 (resolve-module (cdr mod))
922 ;; Either modules have not been booted, or we have a
923 ;; raw symbol coming in, which is possible.
924 (current-module))
925 (id-sym-name id)))
926 (cond
927 ((syntax-object? ni) (free-id=? ni j))
928 ((syntax-object? nj) (free-id=? i nj))
929 ((symbol? ni)
930 ;; `i' is not lexically bound. Assert that `j' is free,
931 ;; and if so, compare their bindings, that they are either
932 ;; bound to the same variable, or both unbound and have
933 ;; the same name.
934 (and (eq? nj (id-sym-name j))
935 (let ((bi (id-module-binding i mi)))
936 (if bi
937 (eq? bi (id-module-binding j mj))
938 (and (not (id-module-binding j mj))
939 (eq? ni nj))))
940 (eq? (id-module-binding i mi) (id-module-binding j mj))))
941 (else
942 ;; Otherwise `i' is bound, so check that `j' is bound, and
943 ;; bound to the same thing.
944 (equal? ni nj))))))
945
946 ;; bound-id=? may be passed unwrapped (or partially wrapped) ids as
947 ;; long as the missing portion of the wrap is common to both of the ids
948 ;; since (bound-id=? x y) iff (bound-id=? (wrap x w) (wrap y w))
949
950 (define bound-id=?
951 (lambda (i j)
952 (if (and (syntax-object? i) (syntax-object? j))
953 (and (eq? (syntax-object-expression i)
954 (syntax-object-expression j))
955 (same-marks? (wrap-marks (syntax-object-wrap i))
956 (wrap-marks (syntax-object-wrap j))))
957 (eq? i j))))
958
959 ;; "valid-bound-ids?" returns #t if it receives a list of distinct ids.
960 ;; valid-bound-ids? may be passed unwrapped (or partially wrapped) ids
961 ;; as long as the missing portion of the wrap is common to all of the
962 ;; ids.
963
964 (define valid-bound-ids?
965 (lambda (ids)
966 (and (let all-ids? ((ids ids))
967 (or (null? ids)
968 (and (id? (car ids))
969 (all-ids? (cdr ids)))))
970 (distinct-bound-ids? ids))))
971
972 ;; distinct-bound-ids? expects a list of ids and returns #t if there are
973 ;; no duplicates. It is quadratic on the length of the id list; long
974 ;; lists could be sorted to make it more efficient. distinct-bound-ids?
975 ;; may be passed unwrapped (or partially wrapped) ids as long as the
976 ;; missing portion of the wrap is common to all of the ids.
977
978 (define distinct-bound-ids?
979 (lambda (ids)
980 (let distinct? ((ids ids))
981 (or (null? ids)
982 (and (not (bound-id-member? (car ids) (cdr ids)))
983 (distinct? (cdr ids)))))))
984
985 (define bound-id-member?
986 (lambda (x list)
987 (and (not (null? list))
988 (or (bound-id=? x (car list))
989 (bound-id-member? x (cdr list))))))
990
991 ;; wrapping expressions and identifiers
992
993 (define wrap
994 (lambda (x w defmod)
995 (cond
996 ((and (null? (wrap-marks w)) (null? (wrap-subst w))) x)
997 ((syntax-object? x)
998 (make-syntax-object
999 (syntax-object-expression x)
1000 (join-wraps w (syntax-object-wrap x))
1001 (syntax-object-module x)))
1002 ((null? x) x)
1003 (else (make-syntax-object x w defmod)))))
1004
1005 (define source-wrap
1006 (lambda (x w s defmod)
1007 (wrap (decorate-source x s) w defmod)))
1008
1009 ;; expanding
1010
1011 (define expand-sequence
1012 (lambda (body r w s mod)
1013 (build-sequence s
1014 (let dobody ((body body) (r r) (w w) (mod mod))
1015 (if (null? body)
1016 '()
1017 (let ((first (expand (car body) r w mod)))
1018 (cons first (dobody (cdr body) r w mod))))))))
1019
1020 ;; At top-level, we allow mixed definitions and expressions. Like
1021 ;; expand-body we expand in two passes.
1022 ;;
1023 ;; First, from left to right, we expand just enough to know what
1024 ;; expressions are definitions, syntax definitions, and splicing
1025 ;; statements (`begin'). If we anything needs evaluating at
1026 ;; expansion-time, it is expanded directly.
1027 ;;
1028 ;; Otherwise we collect expressions to expand, in thunks, and then
1029 ;; expand them all at the end. This allows all syntax expanders
1030 ;; visible in a toplevel sequence to be visible during the
1031 ;; expansions of all normal definitions and expressions in the
1032 ;; sequence.
1033 ;;
1034 (define expand-top-sequence
1035 (lambda (body r w s m esew mod)
1036 (let* ((r (cons '("placeholder" . (placeholder)) r))
1037 (ribcage (make-empty-ribcage))
1038 (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
1039 (define (record-definition! id var)
1040 (let ((mod (cons 'hygiene (module-name (current-module)))))
1041 ;; Ribcages map symbol+marks to names, mostly for
1042 ;; resolving lexicals. Here to add a mapping for toplevel
1043 ;; definitions we also need to match the module. So, we
1044 ;; put it in the name instead, and make id-var-name handle
1045 ;; the special case of names that are pairs. See the
1046 ;; comments in id-var-name for more.
1047 (extend-ribcage! ribcage id
1048 (cons (syntax-object-module id)
1049 (wrap var top-wrap mod)))))
1050 (define (macro-introduced-identifier? id)
1051 (not (equal? (wrap-marks (syntax-object-wrap id)) '(top))))
1052 (define (fresh-derived-name id orig-form)
1053 (symbol-append
1054 (syntax-object-expression id)
1055 '-
1056 (string->symbol
1057 ;; FIXME: `hash' currently stops descending into nested
1058 ;; data at some point, so it's less unique than we would
1059 ;; like. Also this encodes hash values into the ABI of
1060 ;; compiled modules; a problem?
1061 (number->string
1062 (hash (syntax->datum orig-form) most-positive-fixnum)
1063 16))))
1064 (define (parse body r w s m esew mod)
1065 (let lp ((body body) (exps '()))
1066 (if (null? body)
1067 exps
1068 (lp (cdr body)
1069 (append (parse1 (car body) r w s m esew mod)
1070 exps)))))
1071 (define (parse1 x r w s m esew mod)
1072 (call-with-values
1073 (lambda ()
1074 (syntax-type x r w (source-annotation x) ribcage mod #f))
1075 (lambda (type value form e w s mod)
1076 (case type
1077 ((define-form)
1078 (let* ((id (wrap value w mod))
1079 (label (gen-label))
1080 (var (if (macro-introduced-identifier? id)
1081 (fresh-derived-name id x)
1082 (syntax-object-expression id))))
1083 (record-definition! id var)
1084 (list
1085 (if (eq? m 'c&e)
1086 (let ((x (build-global-definition s var (expand e r w mod))))
1087 (top-level-eval-hook x mod)
1088 (lambda () x))
1089 (lambda ()
1090 (build-global-definition s var (expand e r w mod)))))))
1091 ((define-syntax-form define-syntax-parameter-form)
1092 (let* ((id (wrap value w mod))
1093 (label (gen-label))
1094 (var (if (macro-introduced-identifier? id)
1095 (fresh-derived-name id x)
1096 (syntax-object-expression id))))
1097 (record-definition! id var)
1098 (case m
1099 ((c)
1100 (cond
1101 ((memq 'compile esew)
1102 (let ((e (expand-install-global var type (expand e r w mod))))
1103 (top-level-eval-hook e mod)
1104 (if (memq 'load esew)
1105 (list (lambda () e))
1106 '())))
1107 ((memq 'load esew)
1108 (list (lambda ()
1109 (expand-install-global var type (expand e r w mod)))))
1110 (else '())))
1111 ((c&e)
1112 (let ((e (expand-install-global var type (expand e r w mod))))
1113 (top-level-eval-hook e mod)
1114 (list (lambda () e))))
1115 (else
1116 (if (memq 'eval esew)
1117 (top-level-eval-hook
1118 (expand-install-global var type (expand e r w mod))
1119 mod))
1120 '()))))
1121 ((begin-form)
1122 (syntax-case e ()
1123 ((_ e1 ...)
1124 (parse #'(e1 ...) r w s m esew mod))))
1125 ((local-syntax-form)
1126 (expand-local-syntax value e r w s mod
1127 (lambda (forms r w s mod)
1128 (parse forms r w s m esew mod))))
1129 ((eval-when-form)
1130 (syntax-case e ()
1131 ((_ (x ...) e1 e2 ...)
1132 (let ((when-list (parse-when-list e #'(x ...)))
1133 (body #'(e1 e2 ...)))
1134 (define (recurse m esew)
1135 (parse body r w s m esew mod))
1136 (cond
1137 ((eq? m 'e)
1138 (if (memq 'eval when-list)
1139 (recurse (if (memq 'expand when-list) 'c&e 'e)
1140 '(eval))
1141 (begin
1142 (if (memq 'expand when-list)
1143 (top-level-eval-hook
1144 (expand-top-sequence body r w s 'e '(eval) mod)
1145 mod))
1146 '())))
1147 ((memq 'load when-list)
1148 (if (or (memq 'compile when-list)
1149 (memq 'expand when-list)
1150 (and (eq? m 'c&e) (memq 'eval when-list)))
1151 (recurse 'c&e '(compile load))
1152 (if (memq m '(c c&e))
1153 (recurse 'c '(load))
1154 '())))
1155 ((or (memq 'compile when-list)
1156 (memq 'expand when-list)
1157 (and (eq? m 'c&e) (memq 'eval when-list)))
1158 (top-level-eval-hook
1159 (expand-top-sequence body r w s 'e '(eval) mod)
1160 mod)
1161 '())
1162 (else
1163 '()))))))
1164 (else
1165 (list
1166 (if (eq? m 'c&e)
1167 (let ((x (expand-expr type value form e r w s mod)))
1168 (top-level-eval-hook x mod)
1169 (lambda () x))
1170 (lambda ()
1171 (expand-expr type value form e r w s mod)))))))))
1172 (let ((exps (map (lambda (x) (x))
1173 (reverse (parse body r w s m esew mod)))))
1174 (if (null? exps)
1175 (build-void s)
1176 (build-sequence s exps))))))
1177
1178 (define expand-install-global
1179 (lambda (name type e)
1180 (build-global-definition
1181 no-source
1182 name
1183 (build-primcall
1184 no-source
1185 'make-syntax-transformer
1186 (if (eq? type 'define-syntax-parameter-form)
1187 (list (build-data no-source name)
1188 (build-data no-source 'syntax-parameter)
1189 (build-primcall no-source 'list (list e)))
1190 (list (build-data no-source name)
1191 (build-data no-source 'macro)
1192 e))))))
1193
1194 (define parse-when-list
1195 (lambda (e when-list)
1196 ;; `when-list' is syntax'd version of list of situations. We
1197 ;; could match these keywords lexically, via free-id=?, but then
1198 ;; we twingle the definition of eval-when to the bindings of
1199 ;; eval, load, expand, and compile, which is totally unintended.
1200 ;; So do a symbolic match instead.
1201 (let ((result (strip when-list empty-wrap)))
1202 (let lp ((l result))
1203 (if (null? l)
1204 result
1205 (if (memq (car l) '(compile load eval expand))
1206 (lp (cdr l))
1207 (syntax-violation 'eval-when "invalid situation" e
1208 (car l))))))))
1209
1210 ;; syntax-type returns seven values: type, value, form, e, w, s, and
1211 ;; mod. The first two are described in the table below.
1212 ;;
1213 ;; type value explanation
1214 ;; -------------------------------------------------------------------
1215 ;; core procedure core singleton
1216 ;; core-form procedure core form
1217 ;; module-ref procedure @ or @@ singleton
1218 ;; lexical name lexical variable reference
1219 ;; global name global variable reference
1220 ;; begin none begin keyword
1221 ;; define none define keyword
1222 ;; define-syntax none define-syntax keyword
1223 ;; define-syntax-parameter none define-syntax-parameter keyword
1224 ;; local-syntax rec? letrec-syntax/let-syntax keyword
1225 ;; eval-when none eval-when keyword
1226 ;; syntax level pattern variable
1227 ;; displaced-lexical none displaced lexical identifier
1228 ;; lexical-call name call to lexical variable
1229 ;; global-call name call to global variable
1230 ;; primitive-call name call to primitive
1231 ;; call none any other call
1232 ;; begin-form none begin expression
1233 ;; define-form id variable definition
1234 ;; define-syntax-form id syntax definition
1235 ;; define-syntax-parameter-form id syntax parameter definition
1236 ;; local-syntax-form rec? syntax definition
1237 ;; eval-when-form none eval-when form
1238 ;; constant none self-evaluating datum
1239 ;; other none anything else
1240 ;;
1241 ;; form is the entire form. For definition forms (define-form,
1242 ;; define-syntax-form, and define-syntax-parameter-form), e is the
1243 ;; rhs expression. For all others, e is the entire form. w is the
1244 ;; wrap for both form and e. s is the source for the entire form.
1245 ;; mod is the module for both form and e.
1246 ;;
1247 ;; syntax-type expands macros and unwraps as necessary to get to one
1248 ;; of the forms above. It also parses definition forms, although
1249 ;; perhaps this should be done by the consumer.
1250
1251 (define syntax-type
1252 (lambda (e r w s rib mod for-car?)
1253 (cond
1254 ((symbol? e)
1255 (call-with-values (lambda () (resolve-identifier e w r mod #t))
1256 (lambda (type value mod*)
1257 (case type
1258 ((macro)
1259 (if for-car?
1260 (values type value e e w s mod)
1261 (syntax-type (expand-macro value e r w s rib mod)
1262 r empty-wrap s rib mod #f)))
1263 ((global)
1264 ;; Toplevel definitions may resolve to bindings with
1265 ;; different names or in different modules.
1266 (values type value e value w s mod*))
1267 (else (values type value e e w s mod))))))
1268 ((pair? e)
1269 (let ((first (car e)))
1270 (call-with-values
1271 (lambda () (syntax-type first r w s rib mod #t))
1272 (lambda (ftype fval fform fe fw fs fmod)
1273 (case ftype
1274 ((lexical)
1275 (values 'lexical-call fval e e w s mod))
1276 ((global)
1277 (if (equal? fmod '(primitive))
1278 (values 'primitive-call fval e e w s mod)
1279 ;; If we got here via an (@@ ...) expansion, we
1280 ;; need to make sure the fmod information is
1281 ;; propagated back correctly -- hence this
1282 ;; consing.
1283 (values 'global-call (make-syntax-object fval w fmod)
1284 e e w s mod)))
1285 ((macro)
1286 (syntax-type (expand-macro fval e r w s rib mod)
1287 r empty-wrap s rib mod for-car?))
1288 ((module-ref)
1289 (call-with-values (lambda () (fval e r w mod))
1290 (lambda (e r w s mod)
1291 (syntax-type e r w s rib mod for-car?))))
1292 ((core)
1293 (values 'core-form fval e e w s mod))
1294 ((local-syntax)
1295 (values 'local-syntax-form fval e e w s mod))
1296 ((begin)
1297 (values 'begin-form #f e e w s mod))
1298 ((eval-when)
1299 (values 'eval-when-form #f e e w s mod))
1300 ((define)
1301 (syntax-case e ()
1302 ((_ name val)
1303 (id? #'name)
1304 (values 'define-form #'name e #'val w s mod))
1305 ((_ (name . args) e1 e2 ...)
1306 (and (id? #'name)
1307 (valid-bound-ids? (lambda-var-list #'args)))
1308 ;; need lambda here...
1309 (values 'define-form (wrap #'name w mod)
1310 (wrap e w mod)
1311 (decorate-source
1312 (cons #'lambda (wrap #'(args e1 e2 ...) w mod))
1313 s)
1314 empty-wrap s mod))
1315 ((_ name)
1316 (id? #'name)
1317 (values 'define-form (wrap #'name w mod)
1318 (wrap e w mod)
1319 #'(if #f #f)
1320 empty-wrap s mod))))
1321 ((define-syntax)
1322 (syntax-case e ()
1323 ((_ name val)
1324 (id? #'name)
1325 (values 'define-syntax-form #'name e #'val w s mod))))
1326 ((define-syntax-parameter)
1327 (syntax-case e ()
1328 ((_ name val)
1329 (id? #'name)
1330 (values 'define-syntax-parameter-form #'name e #'val w s mod))))
1331 (else
1332 (values 'call #f e e w s mod)))))))
1333 ((syntax-object? e)
1334 (syntax-type (syntax-object-expression e)
1335 r
1336 (join-wraps w (syntax-object-wrap e))
1337 (or (source-annotation e) s) rib
1338 (or (syntax-object-module e) mod) for-car?))
1339 ((self-evaluating? e) (values 'constant #f e e w s mod))
1340 (else (values 'other #f e e w s mod)))))
1341
1342 (define expand
1343 (lambda (e r w mod)
1344 (call-with-values
1345 (lambda () (syntax-type e r w (source-annotation e) #f mod #f))
1346 (lambda (type value form e w s mod)
1347 (expand-expr type value form e r w s mod)))))
1348
1349 (define expand-expr
1350 (lambda (type value form e r w s mod)
1351 (case type
1352 ((lexical)
1353 (build-lexical-reference 'value s e value))
1354 ((core core-form)
1355 ;; apply transformer
1356 (value e r w s mod))
1357 ((module-ref)
1358 (call-with-values (lambda () (value e r w mod))
1359 (lambda (e r w s mod)
1360 (expand e r w mod))))
1361 ((lexical-call)
1362 (expand-call
1363 (let ((id (car e)))
1364 (build-lexical-reference 'fun (source-annotation id)
1365 (if (syntax-object? id)
1366 (syntax->datum id)
1367 id)
1368 value))
1369 e r w s mod))
1370 ((global-call)
1371 (expand-call
1372 (build-global-reference (source-annotation (car e))
1373 (if (syntax-object? value)
1374 (syntax-object-expression value)
1375 value)
1376 (if (syntax-object? value)
1377 (syntax-object-module value)
1378 mod))
1379 e r w s mod))
1380 ((primitive-call)
1381 (syntax-case e ()
1382 ((_ e ...)
1383 (build-primcall s
1384 value
1385 (map (lambda (e) (expand e r w mod))
1386 #'(e ...))))))
1387 ((constant) (build-data s (strip (source-wrap e w s mod) empty-wrap)))
1388 ((global) (build-global-reference s value mod))
1389 ((call) (expand-call (expand (car e) r w mod) e r w s mod))
1390 ((begin-form)
1391 (syntax-case e ()
1392 ((_ e1 e2 ...) (expand-sequence #'(e1 e2 ...) r w s mod))
1393 ((_)
1394 (syntax-violation #f "sequence of zero expressions"
1395 (source-wrap e w s mod)))))
1396 ((local-syntax-form)
1397 (expand-local-syntax value e r w s mod expand-sequence))
1398 ((eval-when-form)
1399 (syntax-case e ()
1400 ((_ (x ...) e1 e2 ...)
1401 (let ((when-list (parse-when-list e #'(x ...))))
1402 (if (memq 'eval when-list)
1403 (expand-sequence #'(e1 e2 ...) r w s mod)
1404 (expand-void))))))
1405 ((define-form define-syntax-form define-syntax-parameter-form)
1406 (syntax-violation #f "definition in expression context, where definitions are not allowed,"
1407 (source-wrap form w s mod)))
1408 ((syntax)
1409 (syntax-violation #f "reference to pattern variable outside syntax form"
1410 (source-wrap e w s mod)))
1411 ((displaced-lexical)
1412 (syntax-violation #f "reference to identifier outside its scope"
1413 (source-wrap e w s mod)))
1414 (else (syntax-violation #f "unexpected syntax"
1415 (source-wrap e w s mod))))))
1416
1417 (define expand-call
1418 (lambda (x e r w s mod)
1419 (syntax-case e ()
1420 ((e0 e1 ...)
1421 (build-call s x
1422 (map (lambda (e) (expand e r w mod)) #'(e1 ...)))))))
1423
1424 ;; (What follows is my interpretation of what's going on here -- Andy)
1425 ;;
1426 ;; A macro takes an expression, a tree, the leaves of which are identifiers
1427 ;; and datums. Identifiers are symbols along with a wrap and a module. For
1428 ;; efficiency, subtrees that share wraps and modules may be grouped as one
1429 ;; syntax object.
1430 ;;
1431 ;; Going into the expansion, the expression is given an anti-mark, which
1432 ;; logically propagates to all leaves. Then, in the new expression returned
1433 ;; from the transfomer, if we see an expression with an anti-mark, we know it
1434 ;; pertains to the original expression; conversely, expressions without the
1435 ;; anti-mark are known to be introduced by the transformer.
1436 ;;
1437 ;; OK, good until now. We know this algorithm does lexical scoping
1438 ;; appropriately because it's widely known in the literature, and psyntax is
1439 ;; widely used. But what about modules? Here we're on our own. What we do is
1440 ;; to mark the module of expressions produced by a macro as pertaining to the
1441 ;; module that was current when the macro was defined -- that is, free
1442 ;; identifiers introduced by a macro are scoped in the macro's module, not in
1443 ;; the expansion's module. Seems to work well.
1444 ;;
1445 ;; The only wrinkle is when we want a macro to expand to code in another
1446 ;; module, as is the case for the r6rs `library' form -- the body expressions
1447 ;; should be scoped relative the the new module, the one defined by the macro.
1448 ;; For that, use `(@@ mod-name body)'.
1449 ;;
1450 ;; Part of the macro output will be from the site of the macro use and part
1451 ;; from the macro definition. We allow source information from the macro use
1452 ;; to pass through, but we annotate the parts coming from the macro with the
1453 ;; source location information corresponding to the macro use. It would be
1454 ;; really nice if we could also annotate introduced expressions with the
1455 ;; locations corresponding to the macro definition, but that is not yet
1456 ;; possible.
1457 (define expand-macro
1458 (lambda (p e r w s rib mod)
1459 (define rebuild-macro-output
1460 (lambda (x m)
1461 (cond ((pair? x)
1462 (decorate-source
1463 (cons (rebuild-macro-output (car x) m)
1464 (rebuild-macro-output (cdr x) m))
1465 s))
1466 ((syntax-object? x)
1467 (let ((w (syntax-object-wrap x)))
1468 (let ((ms (wrap-marks w)) (ss (wrap-subst w)))
1469 (if (and (pair? ms) (eq? (car ms) the-anti-mark))
1470 ;; output is from original text
1471 (make-syntax-object
1472 (syntax-object-expression x)
1473 (make-wrap (cdr ms) (if rib (cons rib (cdr ss)) (cdr ss)))
1474 (syntax-object-module x))
1475 ;; output introduced by macro
1476 (make-syntax-object
1477 (decorate-source (syntax-object-expression x) s)
1478 (make-wrap (cons m ms)
1479 (if rib
1480 (cons rib (cons 'shift ss))
1481 (cons 'shift ss)))
1482 (syntax-object-module x))))))
1483
1484 ((vector? x)
1485 (let* ((n (vector-length x))
1486 (v (decorate-source (make-vector n) s)))
1487 (do ((i 0 (fx+ i 1)))
1488 ((fx= i n) v)
1489 (vector-set! v i
1490 (rebuild-macro-output (vector-ref x i) m)))))
1491 ((symbol? x)
1492 (syntax-violation #f "encountered raw symbol in macro output"
1493 (source-wrap e w (wrap-subst w) mod) x))
1494 (else (decorate-source x s)))))
1495 (with-fluids ((transformer-environment
1496 (lambda (k) (k e r w s rib mod))))
1497 (rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
1498 (new-mark)))))
1499
1500 (define expand-body
1501 ;; In processing the forms of the body, we create a new, empty wrap.
1502 ;; This wrap is augmented (destructively) each time we discover that
1503 ;; the next form is a definition. This is done:
1504 ;;
1505 ;; (1) to allow the first nondefinition form to be a call to
1506 ;; one of the defined ids even if the id previously denoted a
1507 ;; definition keyword or keyword for a macro expanding into a
1508 ;; definition;
1509 ;; (2) to prevent subsequent definition forms (but unfortunately
1510 ;; not earlier ones) and the first nondefinition form from
1511 ;; confusing one of the bound identifiers for an auxiliary
1512 ;; keyword; and
1513 ;; (3) so that we do not need to restart the expansion of the
1514 ;; first nondefinition form, which is problematic anyway
1515 ;; since it might be the first element of a begin that we
1516 ;; have just spliced into the body (meaning if we restarted,
1517 ;; we'd really need to restart with the begin or the macro
1518 ;; call that expanded into the begin, and we'd have to give
1519 ;; up allowing (begin <defn>+ <expr>+), which is itself
1520 ;; problematic since we don't know if a begin contains only
1521 ;; definitions until we've expanded it).
1522 ;;
1523 ;; Before processing the body, we also create a new environment
1524 ;; containing a placeholder for the bindings we will add later and
1525 ;; associate this environment with each form. In processing a
1526 ;; let-syntax or letrec-syntax, the associated environment may be
1527 ;; augmented with local keyword bindings, so the environment may
1528 ;; be different for different forms in the body. Once we have
1529 ;; gathered up all of the definitions, we evaluate the transformer
1530 ;; expressions and splice into r at the placeholder the new variable
1531 ;; and keyword bindings. This allows let-syntax or letrec-syntax
1532 ;; forms local to a portion or all of the body to shadow the
1533 ;; definition bindings.
1534 ;;
1535 ;; Subforms of a begin, let-syntax, or letrec-syntax are spliced
1536 ;; into the body.
1537 ;;
1538 ;; outer-form is fully wrapped w/source
1539 (lambda (body outer-form r w mod)
1540 (let* ((r (cons '("placeholder" . (placeholder)) r))
1541 (ribcage (make-empty-ribcage))
1542 (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
1543 (let parse ((body (map (lambda (x) (cons r (wrap x w mod))) body))
1544 (ids '()) (labels '())
1545 (var-ids '()) (vars '()) (vals '()) (bindings '()))
1546 (if (null? body)
1547 (syntax-violation #f "no expressions in body" outer-form)
1548 (let ((e (cdar body)) (er (caar body)))
1549 (call-with-values
1550 (lambda () (syntax-type e er empty-wrap (source-annotation e) ribcage mod #f))
1551 (lambda (type value form e w s mod)
1552 (case type
1553 ((define-form)
1554 (let ((id (wrap value w mod)) (label (gen-label)))
1555 (let ((var (gen-var id)))
1556 (extend-ribcage! ribcage id label)
1557 (parse (cdr body)
1558 (cons id ids) (cons label labels)
1559 (cons id var-ids)
1560 (cons var vars) (cons (cons er (wrap e w mod)) vals)
1561 (cons (make-binding 'lexical var) bindings)))))
1562 ((define-syntax-form)
1563 (let ((id (wrap value w mod))
1564 (label (gen-label))
1565 (trans-r (macros-only-env er)))
1566 (extend-ribcage! ribcage id label)
1567 ;; As required by R6RS, evaluate the right-hand-sides of internal
1568 ;; syntax definition forms and add their transformers to the
1569 ;; compile-time environment immediately, so that the newly-defined
1570 ;; keywords may be used in definition context within the same
1571 ;; lexical contour.
1572 (set-cdr! r (extend-env
1573 (list label)
1574 (list (make-binding
1575 'macro
1576 (eval-local-transformer
1577 (expand e trans-r w mod)
1578 mod)))
1579 (cdr r)))
1580 (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
1581 ((define-syntax-parameter-form)
1582 ;; Same as define-syntax-form, but different format of the binding.
1583 (let ((id (wrap value w mod))
1584 (label (gen-label))
1585 (trans-r (macros-only-env er)))
1586 (extend-ribcage! ribcage id label)
1587 (set-cdr! r (extend-env
1588 (list label)
1589 (list (make-binding
1590 'syntax-parameter
1591 (list (eval-local-transformer
1592 (expand e trans-r w mod)
1593 mod))))
1594 (cdr r)))
1595 (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
1596 ((begin-form)
1597 (syntax-case e ()
1598 ((_ e1 ...)
1599 (parse (let f ((forms #'(e1 ...)))
1600 (if (null? forms)
1601 (cdr body)
1602 (cons (cons er (wrap (car forms) w mod))
1603 (f (cdr forms)))))
1604 ids labels var-ids vars vals bindings))))
1605 ((local-syntax-form)
1606 (expand-local-syntax value e er w s mod
1607 (lambda (forms er w s mod)
1608 (parse (let f ((forms forms))
1609 (if (null? forms)
1610 (cdr body)
1611 (cons (cons er (wrap (car forms) w mod))
1612 (f (cdr forms)))))
1613 ids labels var-ids vars vals bindings))))
1614 (else ; found a non-definition
1615 (if (null? ids)
1616 (build-sequence no-source
1617 (map (lambda (x)
1618 (expand (cdr x) (car x) empty-wrap mod))
1619 (cons (cons er (source-wrap e w s mod))
1620 (cdr body))))
1621 (begin
1622 (if (not (valid-bound-ids? ids))
1623 (syntax-violation
1624 #f "invalid or duplicate identifier in definition"
1625 outer-form))
1626 (set-cdr! r (extend-env labels bindings (cdr r)))
1627 (build-letrec no-source #t
1628 (reverse (map syntax->datum var-ids))
1629 (reverse vars)
1630 (map (lambda (x)
1631 (expand (cdr x) (car x) empty-wrap mod))
1632 (reverse vals))
1633 (build-sequence no-source
1634 (map (lambda (x)
1635 (expand (cdr x) (car x) empty-wrap mod))
1636 (cons (cons er (source-wrap e w s mod))
1637 (cdr body)))))))))))))))))
1638
1639 (define expand-local-syntax
1640 (lambda (rec? e r w s mod k)
1641 (syntax-case e ()
1642 ((_ ((id val) ...) e1 e2 ...)
1643 (let ((ids #'(id ...)))
1644 (if (not (valid-bound-ids? ids))
1645 (syntax-violation #f "duplicate bound keyword" e)
1646 (let ((labels (gen-labels ids)))
1647 (let ((new-w (make-binding-wrap ids labels w)))
1648 (k #'(e1 e2 ...)
1649 (extend-env
1650 labels
1651 (let ((w (if rec? new-w w))
1652 (trans-r (macros-only-env r)))
1653 (map (lambda (x)
1654 (make-binding 'macro
1655 (eval-local-transformer
1656 (expand x trans-r w mod)
1657 mod)))
1658 #'(val ...)))
1659 r)
1660 new-w
1661 s
1662 mod))))))
1663 (_ (syntax-violation #f "bad local syntax definition"
1664 (source-wrap e w s mod))))))
1665
1666 (define eval-local-transformer
1667 (lambda (expanded mod)
1668 (let ((p (local-eval-hook expanded mod)))
1669 (if (procedure? p)
1670 p
1671 (syntax-violation #f "nonprocedure transformer" p)))))
1672
1673 (define expand-void
1674 (lambda ()
1675 (build-void no-source)))
1676
1677 (define ellipsis?
1678 (lambda (x)
1679 (and (nonsymbol-id? x)
1680 (free-id=? x #'(... ...)))))
1681
1682 (define lambda-formals
1683 (lambda (orig-args)
1684 (define (req args rreq)
1685 (syntax-case args ()
1686 (()
1687 (check (reverse rreq) #f))
1688 ((a . b) (id? #'a)
1689 (req #'b (cons #'a rreq)))
1690 (r (id? #'r)
1691 (check (reverse rreq) #'r))
1692 (else
1693 (syntax-violation 'lambda "invalid argument list" orig-args args))))
1694 (define (check req rest)
1695 (cond
1696 ((distinct-bound-ids? (if rest (cons rest req) req))
1697 (values req #f rest #f))
1698 (else
1699 (syntax-violation 'lambda "duplicate identifier in argument list"
1700 orig-args))))
1701 (req orig-args '())))
1702
1703 (define expand-simple-lambda
1704 (lambda (e r w s mod req rest meta body)
1705 (let* ((ids (if rest (append req (list rest)) req))
1706 (vars (map gen-var ids))
1707 (labels (gen-labels ids)))
1708 (build-simple-lambda
1709 s
1710 (map syntax->datum req) (and rest (syntax->datum rest)) vars
1711 meta
1712 (expand-body body (source-wrap e w s mod)
1713 (extend-var-env labels vars r)
1714 (make-binding-wrap ids labels w)
1715 mod)))))
1716
1717 (define lambda*-formals
1718 (lambda (orig-args)
1719 (define (req args rreq)
1720 (syntax-case args ()
1721 (()
1722 (check (reverse rreq) '() #f '()))
1723 ((a . b) (id? #'a)
1724 (req #'b (cons #'a rreq)))
1725 ((a . b) (eq? (syntax->datum #'a) #:optional)
1726 (opt #'b (reverse rreq) '()))
1727 ((a . b) (eq? (syntax->datum #'a) #:key)
1728 (key #'b (reverse rreq) '() '()))
1729 ((a b) (eq? (syntax->datum #'a) #:rest)
1730 (rest #'b (reverse rreq) '() '()))
1731 (r (id? #'r)
1732 (rest #'r (reverse rreq) '() '()))
1733 (else
1734 (syntax-violation 'lambda* "invalid argument list" orig-args args))))
1735 (define (opt args req ropt)
1736 (syntax-case args ()
1737 (()
1738 (check req (reverse ropt) #f '()))
1739 ((a . b) (id? #'a)
1740 (opt #'b req (cons #'(a #f) ropt)))
1741 (((a init) . b) (id? #'a)
1742 (opt #'b req (cons #'(a init) ropt)))
1743 ((a . b) (eq? (syntax->datum #'a) #:key)
1744 (key #'b req (reverse ropt) '()))
1745 ((a b) (eq? (syntax->datum #'a) #:rest)
1746 (rest #'b req (reverse ropt) '()))
1747 (r (id? #'r)
1748 (rest #'r req (reverse ropt) '()))
1749 (else
1750 (syntax-violation 'lambda* "invalid optional argument list"
1751 orig-args args))))
1752 (define (key args req opt rkey)
1753 (syntax-case args ()
1754 (()
1755 (check req opt #f (cons #f (reverse rkey))))
1756 ((a . b) (id? #'a)
1757 (with-syntax ((k (symbol->keyword (syntax->datum #'a))))
1758 (key #'b req opt (cons #'(k a #f) rkey))))
1759 (((a init) . b) (id? #'a)
1760 (with-syntax ((k (symbol->keyword (syntax->datum #'a))))
1761 (key #'b req opt (cons #'(k a init) rkey))))
1762 (((a init k) . b) (and (id? #'a)
1763 (keyword? (syntax->datum #'k)))
1764 (key #'b req opt (cons #'(k a init) rkey)))
1765 ((aok) (eq? (syntax->datum #'aok) #:allow-other-keys)
1766 (check req opt #f (cons #t (reverse rkey))))
1767 ((aok a b) (and (eq? (syntax->datum #'aok) #:allow-other-keys)
1768 (eq? (syntax->datum #'a) #:rest))
1769 (rest #'b req opt (cons #t (reverse rkey))))
1770 ((aok . r) (and (eq? (syntax->datum #'aok) #:allow-other-keys)
1771 (id? #'r))
1772 (rest #'r req opt (cons #t (reverse rkey))))
1773 ((a b) (eq? (syntax->datum #'a) #:rest)
1774 (rest #'b req opt (cons #f (reverse rkey))))
1775 (r (id? #'r)
1776 (rest #'r req opt (cons #f (reverse rkey))))
1777 (else
1778 (syntax-violation 'lambda* "invalid keyword argument list"
1779 orig-args args))))
1780 (define (rest args req opt kw)
1781 (syntax-case args ()
1782 (r (id? #'r)
1783 (check req opt #'r kw))
1784 (else
1785 (syntax-violation 'lambda* "invalid rest argument"
1786 orig-args args))))
1787 (define (check req opt rest kw)
1788 (cond
1789 ((distinct-bound-ids?
1790 (append req (map car opt) (if rest (list rest) '())
1791 (if (pair? kw) (map cadr (cdr kw)) '())))
1792 (values req opt rest kw))
1793 (else
1794 (syntax-violation 'lambda* "duplicate identifier in argument list"
1795 orig-args))))
1796 (req orig-args '())))
1797
1798 (define expand-lambda-case
1799 (lambda (e r w s mod get-formals clauses)
1800 (define (parse-req req opt rest kw body)
1801 (let ((vars (map gen-var req))
1802 (labels (gen-labels req)))
1803 (let ((r* (extend-var-env labels vars r))
1804 (w* (make-binding-wrap req labels w)))
1805 (parse-opt (map syntax->datum req)
1806 opt rest kw body (reverse vars) r* w* '() '()))))
1807 (define (parse-opt req opt rest kw body vars r* w* out inits)
1808 (cond
1809 ((pair? opt)
1810 (syntax-case (car opt) ()
1811 ((id i)
1812 (let* ((v (gen-var #'id))
1813 (l (gen-labels (list v)))
1814 (r** (extend-var-env l (list v) r*))
1815 (w** (make-binding-wrap (list #'id) l w*)))
1816 (parse-opt req (cdr opt) rest kw body (cons v vars)
1817 r** w** (cons (syntax->datum #'id) out)
1818 (cons (expand #'i r* w* mod) inits))))))
1819 (rest
1820 (let* ((v (gen-var rest))
1821 (l (gen-labels (list v)))
1822 (r* (extend-var-env l (list v) r*))
1823 (w* (make-binding-wrap (list rest) l w*)))
1824 (parse-kw req (if (pair? out) (reverse out) #f)
1825 (syntax->datum rest)
1826 (if (pair? kw) (cdr kw) kw)
1827 body (cons v vars) r* w*
1828 (if (pair? kw) (car kw) #f)
1829 '() inits)))
1830 (else
1831 (parse-kw req (if (pair? out) (reverse out) #f) #f
1832 (if (pair? kw) (cdr kw) kw)
1833 body vars r* w*
1834 (if (pair? kw) (car kw) #f)
1835 '() inits))))
1836 (define (parse-kw req opt rest kw body vars r* w* aok out inits)
1837 (cond
1838 ((pair? kw)
1839 (syntax-case (car kw) ()
1840 ((k id i)
1841 (let* ((v (gen-var #'id))
1842 (l (gen-labels (list v)))
1843 (r** (extend-var-env l (list v) r*))
1844 (w** (make-binding-wrap (list #'id) l w*)))
1845 (parse-kw req opt rest (cdr kw) body (cons v vars)
1846 r** w** aok
1847 (cons (list (syntax->datum #'k)
1848 (syntax->datum #'id)
1849 v)
1850 out)
1851 (cons (expand #'i r* w* mod) inits))))))
1852 (else
1853 (parse-body req opt rest
1854 (if (or aok (pair? out)) (cons aok (reverse out)) #f)
1855 body (reverse vars) r* w* (reverse inits) '()))))
1856 (define (parse-body req opt rest kw body vars r* w* inits meta)
1857 (syntax-case body ()
1858 ((docstring e1 e2 ...) (string? (syntax->datum #'docstring))
1859 (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
1860 (append meta
1861 `((documentation
1862 . ,(syntax->datum #'docstring))))))
1863 ((#((k . v) ...) e1 e2 ...)
1864 (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
1865 (append meta (syntax->datum #'((k . v) ...)))))
1866 ((e1 e2 ...)
1867 (values meta req opt rest kw inits vars
1868 (expand-body #'(e1 e2 ...) (source-wrap e w s mod)
1869 r* w* mod)))))
1870
1871 (syntax-case clauses ()
1872 (() (values '() #f))
1873 (((args e1 e2 ...) (args* e1* e2* ...) ...)
1874 (call-with-values (lambda () (get-formals #'args))
1875 (lambda (req opt rest kw)
1876 (call-with-values (lambda ()
1877 (parse-req req opt rest kw #'(e1 e2 ...)))
1878 (lambda (meta req opt rest kw inits vars body)
1879 (call-with-values
1880 (lambda ()
1881 (expand-lambda-case e r w s mod get-formals
1882 #'((args* e1* e2* ...) ...)))
1883 (lambda (meta* else*)
1884 (values
1885 (append meta meta*)
1886 (build-lambda-case s req opt rest kw inits vars
1887 body else*))))))))))))
1888
1889 ;; data
1890
1891 ;; strips syntax-objects down to top-wrap
1892 ;;
1893 ;; since only the head of a list is annotated by the reader, not each pair
1894 ;; in the spine, we also check for pairs whose cars are annotated in case
1895 ;; we've been passed the cdr of an annotated list
1896
1897 (define strip
1898 (lambda (x w)
1899 (if (top-marked? w)
1900 x
1901 (let f ((x x))
1902 (cond
1903 ((syntax-object? x)
1904 (strip (syntax-object-expression x) (syntax-object-wrap x)))
1905 ((pair? x)
1906 (let ((a (f (car x))) (d (f (cdr x))))
1907 (if (and (eq? a (car x)) (eq? d (cdr x)))
1908 x
1909 (cons a d))))
1910 ((vector? x)
1911 (let ((old (vector->list x)))
1912 (let ((new (map f old)))
1913 ;; inlined and-map with two args
1914 (let lp ((l1 old) (l2 new))
1915 (if (null? l1)
1916 x
1917 (if (eq? (car l1) (car l2))
1918 (lp (cdr l1) (cdr l2))
1919 (list->vector new)))))))
1920 (else x))))))
1921
1922 ;; lexical variables
1923
1924 (define gen-var
1925 (lambda (id)
1926 (let ((id (if (syntax-object? id) (syntax-object-expression id) id)))
1927 (build-lexical-var no-source id))))
1928
1929 ;; appears to return a reversed list
1930 (define lambda-var-list
1931 (lambda (vars)
1932 (let lvl ((vars vars) (ls '()) (w empty-wrap))
1933 (cond
1934 ((pair? vars) (lvl (cdr vars) (cons (wrap (car vars) w #f) ls) w))
1935 ((id? vars) (cons (wrap vars w #f) ls))
1936 ((null? vars) ls)
1937 ((syntax-object? vars)
1938 (lvl (syntax-object-expression vars)
1939 ls
1940 (join-wraps w (syntax-object-wrap vars))))
1941 ;; include anything else to be caught by subsequent error
1942 ;; checking
1943 (else (cons vars ls))))))
1944
1945 ;; core transformers
1946
1947 (global-extend 'local-syntax 'letrec-syntax #t)
1948 (global-extend 'local-syntax 'let-syntax #f)
1949
1950 (global-extend
1951 'core 'syntax-parameterize
1952 (lambda (e r w s mod)
1953 (syntax-case e ()
1954 ((_ ((var val) ...) e1 e2 ...)
1955 (valid-bound-ids? #'(var ...))
1956 (let ((names
1957 (map (lambda (x)
1958 (call-with-values
1959 (lambda () (resolve-identifier x w r mod #f))
1960 (lambda (type value mod)
1961 (case type
1962 ((displaced-lexical)
1963 (syntax-violation 'syntax-parameterize
1964 "identifier out of context"
1965 e
1966 (source-wrap x w s mod)))
1967 ((syntax-parameter)
1968 value)
1969 (else
1970 (syntax-violation 'syntax-parameterize
1971 "invalid syntax parameter"
1972 e
1973 (source-wrap x w s mod)))))))
1974 #'(var ...)))
1975 (bindings
1976 (let ((trans-r (macros-only-env r)))
1977 (map (lambda (x)
1978 (make-binding
1979 'macro
1980 (eval-local-transformer (expand x trans-r w mod) mod)))
1981 #'(val ...)))))
1982 (expand-body #'(e1 e2 ...)
1983 (source-wrap e w s mod)
1984 (extend-env names bindings r)
1985 w
1986 mod)))
1987 (_ (syntax-violation 'syntax-parameterize "bad syntax"
1988 (source-wrap e w s mod))))))
1989
1990 (global-extend 'core 'quote
1991 (lambda (e r w s mod)
1992 (syntax-case e ()
1993 ((_ e) (build-data s (strip #'e w)))
1994 (_ (syntax-violation 'quote "bad syntax"
1995 (source-wrap e w s mod))))))
1996
1997 (global-extend
1998 'core 'syntax
1999 (let ()
2000 (define gen-syntax
2001 (lambda (src e r maps ellipsis? mod)
2002 (if (id? e)
2003 (call-with-values (lambda ()
2004 (resolve-identifier e empty-wrap r mod #f))
2005 (lambda (type value mod)
2006 (case type
2007 ((syntax)
2008 (call-with-values
2009 (lambda () (gen-ref src (car value) (cdr value) maps))
2010 (lambda (var maps)
2011 (values `(ref ,var) maps))))
2012 (else
2013 (if (ellipsis? e)
2014 (syntax-violation 'syntax "misplaced ellipsis" src)
2015 (values `(quote ,e) maps))))))
2016 (syntax-case e ()
2017 ((dots e)
2018 (ellipsis? #'dots)
2019 (gen-syntax src #'e r maps (lambda (x) #f) mod))
2020 ((x dots . y)
2021 ;; this could be about a dozen lines of code, except that we
2022 ;; choose to handle #'(x ... ...) forms
2023 (ellipsis? #'dots)
2024 (let f ((y #'y)
2025 (k (lambda (maps)
2026 (call-with-values
2027 (lambda ()
2028 (gen-syntax src #'x r
2029 (cons '() maps) ellipsis? mod))
2030 (lambda (x maps)
2031 (if (null? (car maps))
2032 (syntax-violation 'syntax "extra ellipsis"
2033 src)
2034 (values (gen-map x (car maps))
2035 (cdr maps))))))))
2036 (syntax-case y ()
2037 ((dots . y)
2038 (ellipsis? #'dots)
2039 (f #'y
2040 (lambda (maps)
2041 (call-with-values
2042 (lambda () (k (cons '() maps)))
2043 (lambda (x maps)
2044 (if (null? (car maps))
2045 (syntax-violation 'syntax "extra ellipsis" src)
2046 (values (gen-mappend x (car maps))
2047 (cdr maps))))))))
2048 (_ (call-with-values
2049 (lambda () (gen-syntax src y r maps ellipsis? mod))
2050 (lambda (y maps)
2051 (call-with-values
2052 (lambda () (k maps))
2053 (lambda (x maps)
2054 (values (gen-append x y) maps)))))))))
2055 ((x . y)
2056 (call-with-values
2057 (lambda () (gen-syntax src #'x r maps ellipsis? mod))
2058 (lambda (x maps)
2059 (call-with-values
2060 (lambda () (gen-syntax src #'y r maps ellipsis? mod))
2061 (lambda (y maps) (values (gen-cons x y) maps))))))
2062 (#(e1 e2 ...)
2063 (call-with-values
2064 (lambda ()
2065 (gen-syntax src #'(e1 e2 ...) r maps ellipsis? mod))
2066 (lambda (e maps) (values (gen-vector e) maps))))
2067 (_ (values `(quote ,e) maps))))))
2068
2069 (define gen-ref
2070 (lambda (src var level maps)
2071 (if (fx= level 0)
2072 (values var maps)
2073 (if (null? maps)
2074 (syntax-violation 'syntax "missing ellipsis" src)
2075 (call-with-values
2076 (lambda () (gen-ref src var (fx- level 1) (cdr maps)))
2077 (lambda (outer-var outer-maps)
2078 (let ((b (assq outer-var (car maps))))
2079 (if b
2080 (values (cdr b) maps)
2081 (let ((inner-var (gen-var 'tmp)))
2082 (values inner-var
2083 (cons (cons (cons outer-var inner-var)
2084 (car maps))
2085 outer-maps)))))))))))
2086
2087 (define gen-mappend
2088 (lambda (e map-env)
2089 `(apply (primitive append) ,(gen-map e map-env))))
2090
2091 (define gen-map
2092 (lambda (e map-env)
2093 (let ((formals (map cdr map-env))
2094 (actuals (map (lambda (x) `(ref ,(car x))) map-env)))
2095 (cond
2096 ((eq? (car e) 'ref)
2097 ;; identity map equivalence:
2098 ;; (map (lambda (x) x) y) == y
2099 (car actuals))
2100 ((and-map
2101 (lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
2102 (cdr e))
2103 ;; eta map equivalence:
2104 ;; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
2105 `(map (primitive ,(car e))
2106 ,@(map (let ((r (map cons formals actuals)))
2107 (lambda (x) (cdr (assq (cadr x) r))))
2108 (cdr e))))
2109 (else `(map (lambda ,formals ,e) ,@actuals))))))
2110
2111 (define gen-cons
2112 (lambda (x y)
2113 (case (car y)
2114 ((quote)
2115 (if (eq? (car x) 'quote)
2116 `(quote (,(cadr x) . ,(cadr y)))
2117 (if (eq? (cadr y) '())
2118 `(list ,x)
2119 `(cons ,x ,y))))
2120 ((list) `(list ,x ,@(cdr y)))
2121 (else `(cons ,x ,y)))))
2122
2123 (define gen-append
2124 (lambda (x y)
2125 (if (equal? y '(quote ()))
2126 x
2127 `(append ,x ,y))))
2128
2129 (define gen-vector
2130 (lambda (x)
2131 (cond
2132 ((eq? (car x) 'list) `(vector ,@(cdr x)))
2133 ((eq? (car x) 'quote) `(quote #(,@(cadr x))))
2134 (else `(list->vector ,x)))))
2135
2136
2137 (define regen
2138 (lambda (x)
2139 (case (car x)
2140 ((ref) (build-lexical-reference 'value no-source (cadr x) (cadr x)))
2141 ((primitive) (build-primref no-source (cadr x)))
2142 ((quote) (build-data no-source (cadr x)))
2143 ((lambda)
2144 (if (list? (cadr x))
2145 (build-simple-lambda no-source (cadr x) #f (cadr x) '() (regen (caddr x)))
2146 (error "how did we get here" x)))
2147 (else (build-primcall no-source (car x) (map regen (cdr x)))))))
2148
2149 (lambda (e r w s mod)
2150 (let ((e (source-wrap e w s mod)))
2151 (syntax-case e ()
2152 ((_ x)
2153 (call-with-values
2154 (lambda () (gen-syntax e #'x r '() ellipsis? mod))
2155 (lambda (e maps) (regen e))))
2156 (_ (syntax-violation 'syntax "bad `syntax' form" e)))))))
2157
2158 (global-extend 'core 'lambda
2159 (lambda (e r w s mod)
2160 (syntax-case e ()
2161 ((_ args e1 e2 ...)
2162 (call-with-values (lambda () (lambda-formals #'args))
2163 (lambda (req opt rest kw)
2164 (let lp ((body #'(e1 e2 ...)) (meta '()))
2165 (syntax-case body ()
2166 ((docstring e1 e2 ...) (string? (syntax->datum #'docstring))
2167 (lp #'(e1 e2 ...)
2168 (append meta
2169 `((documentation
2170 . ,(syntax->datum #'docstring))))))
2171 ((#((k . v) ...) e1 e2 ...)
2172 (lp #'(e1 e2 ...)
2173 (append meta (syntax->datum #'((k . v) ...)))))
2174 (_ (expand-simple-lambda e r w s mod req rest meta body)))))))
2175 (_ (syntax-violation 'lambda "bad lambda" e)))))
2176
2177 (global-extend 'core 'lambda*
2178 (lambda (e r w s mod)
2179 (syntax-case e ()
2180 ((_ args e1 e2 ...)
2181 (call-with-values
2182 (lambda ()
2183 (expand-lambda-case e r w s mod
2184 lambda*-formals #'((args e1 e2 ...))))
2185 (lambda (meta lcase)
2186 (build-case-lambda s meta lcase))))
2187 (_ (syntax-violation 'lambda "bad lambda*" e)))))
2188
2189 (global-extend 'core 'case-lambda
2190 (lambda (e r w s mod)
2191 (define (build-it meta clauses)
2192 (call-with-values
2193 (lambda ()
2194 (expand-lambda-case e r w s mod
2195 lambda-formals
2196 clauses))
2197 (lambda (meta* lcase)
2198 (build-case-lambda s (append meta meta*) lcase))))
2199 (syntax-case e ()
2200 ((_ (args e1 e2 ...) ...)
2201 (build-it '() #'((args e1 e2 ...) ...)))
2202 ((_ docstring (args e1 e2 ...) ...)
2203 (string? (syntax->datum #'docstring))
2204 (build-it `((documentation
2205 . ,(syntax->datum #'docstring)))
2206 #'((args e1 e2 ...) ...)))
2207 (_ (syntax-violation 'case-lambda "bad case-lambda" e)))))
2208
2209 (global-extend 'core 'case-lambda*
2210 (lambda (e r w s mod)
2211 (define (build-it meta clauses)
2212 (call-with-values
2213 (lambda ()
2214 (expand-lambda-case e r w s mod
2215 lambda*-formals
2216 clauses))
2217 (lambda (meta* lcase)
2218 (build-case-lambda s (append meta meta*) lcase))))
2219 (syntax-case e ()
2220 ((_ (args e1 e2 ...) ...)
2221 (build-it '() #'((args e1 e2 ...) ...)))
2222 ((_ docstring (args e1 e2 ...) ...)
2223 (string? (syntax->datum #'docstring))
2224 (build-it `((documentation
2225 . ,(syntax->datum #'docstring)))
2226 #'((args e1 e2 ...) ...)))
2227 (_ (syntax-violation 'case-lambda "bad case-lambda*" e)))))
2228
2229 (global-extend 'core 'let
2230 (let ()
2231 (define (expand-let e r w s mod constructor ids vals exps)
2232 (if (not (valid-bound-ids? ids))
2233 (syntax-violation 'let "duplicate bound variable" e)
2234 (let ((labels (gen-labels ids))
2235 (new-vars (map gen-var ids)))
2236 (let ((nw (make-binding-wrap ids labels w))
2237 (nr (extend-var-env labels new-vars r)))
2238 (constructor s
2239 (map syntax->datum ids)
2240 new-vars
2241 (map (lambda (x) (expand x r w mod)) vals)
2242 (expand-body exps (source-wrap e nw s mod)
2243 nr nw mod))))))
2244 (lambda (e r w s mod)
2245 (syntax-case e ()
2246 ((_ ((id val) ...) e1 e2 ...)
2247 (and-map id? #'(id ...))
2248 (expand-let e r w s mod
2249 build-let
2250 #'(id ...)
2251 #'(val ...)
2252 #'(e1 e2 ...)))
2253 ((_ f ((id val) ...) e1 e2 ...)
2254 (and (id? #'f) (and-map id? #'(id ...)))
2255 (expand-let e r w s mod
2256 build-named-let
2257 #'(f id ...)
2258 #'(val ...)
2259 #'(e1 e2 ...)))
2260 (_ (syntax-violation 'let "bad let" (source-wrap e w s mod)))))))
2261
2262
2263 (global-extend 'core 'letrec
2264 (lambda (e r w s mod)
2265 (syntax-case e ()
2266 ((_ ((id val) ...) e1 e2 ...)
2267 (and-map id? #'(id ...))
2268 (let ((ids #'(id ...)))
2269 (if (not (valid-bound-ids? ids))
2270 (syntax-violation 'letrec "duplicate bound variable" e)
2271 (let ((labels (gen-labels ids))
2272 (new-vars (map gen-var ids)))
2273 (let ((w (make-binding-wrap ids labels w))
2274 (r (extend-var-env labels new-vars r)))
2275 (build-letrec s #f
2276 (map syntax->datum ids)
2277 new-vars
2278 (map (lambda (x) (expand x r w mod)) #'(val ...))
2279 (expand-body #'(e1 e2 ...)
2280 (source-wrap e w s mod) r w mod)))))))
2281 (_ (syntax-violation 'letrec "bad letrec" (source-wrap e w s mod))))))
2282
2283
2284 (global-extend 'core 'letrec*
2285 (lambda (e r w s mod)
2286 (syntax-case e ()
2287 ((_ ((id val) ...) e1 e2 ...)
2288 (and-map id? #'(id ...))
2289 (let ((ids #'(id ...)))
2290 (if (not (valid-bound-ids? ids))
2291 (syntax-violation 'letrec* "duplicate bound variable" e)
2292 (let ((labels (gen-labels ids))
2293 (new-vars (map gen-var ids)))
2294 (let ((w (make-binding-wrap ids labels w))
2295 (r (extend-var-env labels new-vars r)))
2296 (build-letrec s #t
2297 (map syntax->datum ids)
2298 new-vars
2299 (map (lambda (x) (expand x r w mod)) #'(val ...))
2300 (expand-body #'(e1 e2 ...)
2301 (source-wrap e w s mod) r w mod)))))))
2302 (_ (syntax-violation 'letrec* "bad letrec*" (source-wrap e w s mod))))))
2303
2304
2305 (global-extend
2306 'core 'set!
2307 (lambda (e r w s mod)
2308 (syntax-case e ()
2309 ((_ id val)
2310 (id? #'id)
2311 (call-with-values
2312 (lambda () (resolve-identifier #'id w r mod #t))
2313 (lambda (type value id-mod)
2314 (case type
2315 ((lexical)
2316 (build-lexical-assignment s (syntax->datum #'id) value
2317 (expand #'val r w mod)))
2318 ((global)
2319 (build-global-assignment s value (expand #'val r w mod) id-mod))
2320 ((macro)
2321 (if (procedure-property value 'variable-transformer)
2322 ;; As syntax-type does, call expand-macro with
2323 ;; the mod of the expression. Hmm.
2324 (expand (expand-macro value e r w s #f mod) r empty-wrap mod)
2325 (syntax-violation 'set! "not a variable transformer"
2326 (wrap e w mod)
2327 (wrap #'id w id-mod))))
2328 ((displaced-lexical)
2329 (syntax-violation 'set! "identifier out of context"
2330 (wrap #'id w mod)))
2331 (else
2332 (syntax-violation 'set! "bad set!" (source-wrap e w s mod)))))))
2333 ((_ (head tail ...) val)
2334 (call-with-values
2335 (lambda () (syntax-type #'head r empty-wrap no-source #f mod #t))
2336 (lambda (type value ee* ee ww ss modmod)
2337 (case type
2338 ((module-ref)
2339 (let ((val (expand #'val r w mod)))
2340 (call-with-values (lambda () (value #'(head tail ...) r w mod))
2341 (lambda (e r w s* mod)
2342 (syntax-case e ()
2343 (e (id? #'e)
2344 (build-global-assignment s (syntax->datum #'e)
2345 val mod)))))))
2346 (else
2347 (build-call s
2348 (expand #'(setter head) r w mod)
2349 (map (lambda (e) (expand e r w mod))
2350 #'(tail ... val))))))))
2351 (_ (syntax-violation 'set! "bad set!" (source-wrap e w s mod))))))
2352
2353 (global-extend 'module-ref '@
2354 (lambda (e r w mod)
2355 (syntax-case e ()
2356 ((_ (mod ...) id)
2357 (and (and-map id? #'(mod ...)) (id? #'id))
2358 ;; Strip the wrap from the identifier and return top-wrap
2359 ;; so that the identifier will not be captured by lexicals.
2360 (values (syntax->datum #'id) r top-wrap #f
2361 (syntax->datum
2362 #'(public mod ...)))))))
2363
2364 (global-extend 'module-ref '@@
2365 (lambda (e r w mod)
2366 (define remodulate
2367 (lambda (x mod)
2368 (cond ((pair? x)
2369 (cons (remodulate (car x) mod)
2370 (remodulate (cdr x) mod)))
2371 ((syntax-object? x)
2372 (make-syntax-object
2373 (remodulate (syntax-object-expression x) mod)
2374 (syntax-object-wrap x)
2375 ;; hither the remodulation
2376 mod))
2377 ((vector? x)
2378 (let* ((n (vector-length x)) (v (make-vector n)))
2379 (do ((i 0 (fx+ i 1)))
2380 ((fx= i n) v)
2381 (vector-set! v i (remodulate (vector-ref x i) mod)))))
2382 (else x))))
2383 (syntax-case e (@@ primitive)
2384 ((_ primitive id)
2385 (and (id? #'id)
2386 (equal? (cdr (if (syntax-object? #'id)
2387 (syntax-object-module #'id)
2388 mod))
2389 '(guile)))
2390 ;; Strip the wrap from the identifier and return top-wrap
2391 ;; so that the identifier will not be captured by lexicals.
2392 (values (syntax->datum #'id) r top-wrap #f '(primitive)))
2393 ((_ (mod ...) id)
2394 (and (and-map id? #'(mod ...)) (id? #'id))
2395 ;; Strip the wrap from the identifier and return top-wrap
2396 ;; so that the identifier will not be captured by lexicals.
2397 (values (syntax->datum #'id) r top-wrap #f
2398 (syntax->datum
2399 #'(private mod ...))))
2400 ((_ @@ (mod ...) exp)
2401 (and-map id? #'(mod ...))
2402 ;; This is a special syntax used to support R6RS library forms.
2403 ;; Unlike the syntax above, the last item is not restricted to
2404 ;; be a single identifier, and the syntax objects are kept
2405 ;; intact, with only their module changed.
2406 (let ((mod (syntax->datum #'(private mod ...))))
2407 (values (remodulate #'exp mod)
2408 r w (source-annotation #'exp)
2409 mod))))))
2410
2411 (global-extend 'core 'if
2412 (lambda (e r w s mod)
2413 (syntax-case e ()
2414 ((_ test then)
2415 (build-conditional
2416 s
2417 (expand #'test r w mod)
2418 (expand #'then r w mod)
2419 (build-void no-source)))
2420 ((_ test then else)
2421 (build-conditional
2422 s
2423 (expand #'test r w mod)
2424 (expand #'then r w mod)
2425 (expand #'else r w mod))))))
2426
2427 (global-extend 'begin 'begin '())
2428
2429 (global-extend 'define 'define '())
2430
2431 (global-extend 'define-syntax 'define-syntax '())
2432 (global-extend 'define-syntax-parameter 'define-syntax-parameter '())
2433
2434 (global-extend 'eval-when 'eval-when '())
2435
2436 (global-extend 'core 'syntax-case
2437 (let ()
2438 (define convert-pattern
2439 ;; accepts pattern & keys
2440 ;; returns $sc-dispatch pattern & ids
2441 (lambda (pattern keys)
2442 (define cvt*
2443 (lambda (p* n ids)
2444 (if (not (pair? p*))
2445 (cvt p* n ids)
2446 (call-with-values
2447 (lambda () (cvt* (cdr p*) n ids))
2448 (lambda (y ids)
2449 (call-with-values
2450 (lambda () (cvt (car p*) n ids))
2451 (lambda (x ids)
2452 (values (cons x y) ids))))))))
2453
2454 (define (v-reverse x)
2455 (let loop ((r '()) (x x))
2456 (if (not (pair? x))
2457 (values r x)
2458 (loop (cons (car x) r) (cdr x)))))
2459
2460 (define cvt
2461 (lambda (p n ids)
2462 (if (id? p)
2463 (cond
2464 ((bound-id-member? p keys)
2465 (values (vector 'free-id p) ids))
2466 ((free-id=? p #'_)
2467 (values '_ ids))
2468 (else
2469 (values 'any (cons (cons p n) ids))))
2470 (syntax-case p ()
2471 ((x dots)
2472 (ellipsis? (syntax dots))
2473 (call-with-values
2474 (lambda () (cvt (syntax x) (fx+ n 1) ids))
2475 (lambda (p ids)
2476 (values (if (eq? p 'any) 'each-any (vector 'each p))
2477 ids))))
2478 ((x dots . ys)
2479 (ellipsis? (syntax dots))
2480 (call-with-values
2481 (lambda () (cvt* (syntax ys) n ids))
2482 (lambda (ys ids)
2483 (call-with-values
2484 (lambda () (cvt (syntax x) (+ n 1) ids))
2485 (lambda (x ids)
2486 (call-with-values
2487 (lambda () (v-reverse ys))
2488 (lambda (ys e)
2489 (values `#(each+ ,x ,ys ,e)
2490 ids))))))))
2491 ((x . y)
2492 (call-with-values
2493 (lambda () (cvt (syntax y) n ids))
2494 (lambda (y ids)
2495 (call-with-values
2496 (lambda () (cvt (syntax x) n ids))
2497 (lambda (x ids)
2498 (values (cons x y) ids))))))
2499 (() (values '() ids))
2500 (#(x ...)
2501 (call-with-values
2502 (lambda () (cvt (syntax (x ...)) n ids))
2503 (lambda (p ids) (values (vector 'vector p) ids))))
2504 (x (values (vector 'atom (strip p empty-wrap)) ids))))))
2505 (cvt pattern 0 '())))
2506
2507 (define build-dispatch-call
2508 (lambda (pvars exp y r mod)
2509 (let ((ids (map car pvars)) (levels (map cdr pvars)))
2510 (let ((labels (gen-labels ids)) (new-vars (map gen-var ids)))
2511 (build-primcall
2512 no-source
2513 'apply
2514 (list (build-simple-lambda no-source (map syntax->datum ids) #f new-vars '()
2515 (expand exp
2516 (extend-env
2517 labels
2518 (map (lambda (var level)
2519 (make-binding 'syntax `(,var . ,level)))
2520 new-vars
2521 (map cdr pvars))
2522 r)
2523 (make-binding-wrap ids labels empty-wrap)
2524 mod))
2525 y))))))
2526
2527 (define gen-clause
2528 (lambda (x keys clauses r pat fender exp mod)
2529 (call-with-values
2530 (lambda () (convert-pattern pat keys))
2531 (lambda (p pvars)
2532 (cond
2533 ((not (distinct-bound-ids? (map car pvars)))
2534 (syntax-violation 'syntax-case "duplicate pattern variable" pat))
2535 ((not (and-map (lambda (x) (not (ellipsis? (car x)))) pvars))
2536 (syntax-violation 'syntax-case "misplaced ellipsis" pat))
2537 (else
2538 (let ((y (gen-var 'tmp)))
2539 ;; fat finger binding and references to temp variable y
2540 (build-call no-source
2541 (build-simple-lambda no-source (list 'tmp) #f (list y) '()
2542 (let ((y (build-lexical-reference 'value no-source
2543 'tmp y)))
2544 (build-conditional no-source
2545 (syntax-case fender ()
2546 (#t y)
2547 (_ (build-conditional no-source
2548 y
2549 (build-dispatch-call pvars fender y r mod)
2550 (build-data no-source #f))))
2551 (build-dispatch-call pvars exp y r mod)
2552 (gen-syntax-case x keys clauses r mod))))
2553 (list (if (eq? p 'any)
2554 (build-primcall no-source 'list (list x))
2555 (build-primcall no-source '$sc-dispatch
2556 (list x (build-data no-source p)))))))))))))
2557
2558 (define gen-syntax-case
2559 (lambda (x keys clauses r mod)
2560 (if (null? clauses)
2561 (build-primcall no-source 'syntax-violation
2562 (list (build-data no-source #f)
2563 (build-data no-source
2564 "source expression failed to match any pattern")
2565 x))
2566 (syntax-case (car clauses) ()
2567 ((pat exp)
2568 (if (and (id? #'pat)
2569 (and-map (lambda (x) (not (free-id=? #'pat x)))
2570 (cons #'(... ...) keys)))
2571 (if (free-id=? #'pat #'_)
2572 (expand #'exp r empty-wrap mod)
2573 (let ((labels (list (gen-label)))
2574 (var (gen-var #'pat)))
2575 (build-call no-source
2576 (build-simple-lambda
2577 no-source (list (syntax->datum #'pat)) #f (list var)
2578 '()
2579 (expand #'exp
2580 (extend-env labels
2581 (list (make-binding 'syntax `(,var . 0)))
2582 r)
2583 (make-binding-wrap #'(pat)
2584 labels empty-wrap)
2585 mod))
2586 (list x))))
2587 (gen-clause x keys (cdr clauses) r
2588 #'pat #t #'exp mod)))
2589 ((pat fender exp)
2590 (gen-clause x keys (cdr clauses) r
2591 #'pat #'fender #'exp mod))
2592 (_ (syntax-violation 'syntax-case "invalid clause"
2593 (car clauses)))))))
2594
2595 (lambda (e r w s mod)
2596 (let ((e (source-wrap e w s mod)))
2597 (syntax-case e ()
2598 ((_ val (key ...) m ...)
2599 (if (and-map (lambda (x) (and (id? x) (not (ellipsis? x))))
2600 #'(key ...))
2601 (let ((x (gen-var 'tmp)))
2602 ;; fat finger binding and references to temp variable x
2603 (build-call s
2604 (build-simple-lambda no-source (list 'tmp) #f (list x) '()
2605 (gen-syntax-case (build-lexical-reference 'value no-source
2606 'tmp x)
2607 #'(key ...) #'(m ...)
2608 r
2609 mod))
2610 (list (expand #'val r empty-wrap mod))))
2611 (syntax-violation 'syntax-case "invalid literals list" e))))))))
2612
2613 ;; The portable macroexpand seeds expand-top's mode m with 'e (for
2614 ;; evaluating) and esew (which stands for "eval syntax expanders
2615 ;; when") with '(eval). In Chez Scheme, m is set to 'c instead of e
2616 ;; if we are compiling a file, and esew is set to
2617 ;; (eval-syntactic-expanders-when), which defaults to the list
2618 ;; '(compile load eval). This means that, by default, top-level
2619 ;; syntactic definitions are evaluated immediately after they are
2620 ;; expanded, and the expanded definitions are also residualized into
2621 ;; the object file if we are compiling a file.
2622 (set! macroexpand
2623 (lambda* (x #:optional (m 'e) (esew '(eval)))
2624 (expand-top-sequence (list x) null-env top-wrap #f m esew
2625 (cons 'hygiene (module-name (current-module))))))
2626
2627 (set! identifier?
2628 (lambda (x)
2629 (nonsymbol-id? x)))
2630
2631 (set! datum->syntax
2632 (lambda (id datum)
2633 (make-syntax-object datum (syntax-object-wrap id)
2634 (syntax-object-module id))))
2635
2636 (set! syntax->datum
2637 ;; accepts any object, since syntax objects may consist partially
2638 ;; or entirely of unwrapped, nonsymbolic data
2639 (lambda (x)
2640 (strip x empty-wrap)))
2641
2642 (set! syntax-source
2643 (lambda (x) (source-annotation x)))
2644
2645 (set! generate-temporaries
2646 (lambda (ls)
2647 (arg-check list? ls 'generate-temporaries)
2648 (let ((mod (cons 'hygiene (module-name (current-module)))))
2649 (map (lambda (x) (wrap (gensym "t-") top-wrap mod)) ls))))
2650
2651 (set! free-identifier=?
2652 (lambda (x y)
2653 (arg-check nonsymbol-id? x 'free-identifier=?)
2654 (arg-check nonsymbol-id? y 'free-identifier=?)
2655 (free-id=? x y)))
2656
2657 (set! bound-identifier=?
2658 (lambda (x y)
2659 (arg-check nonsymbol-id? x 'bound-identifier=?)
2660 (arg-check nonsymbol-id? y 'bound-identifier=?)
2661 (bound-id=? x y)))
2662
2663 (set! syntax-violation
2664 (lambda* (who message form #:optional subform)
2665 (arg-check (lambda (x) (or (not x) (string? x) (symbol? x)))
2666 who 'syntax-violation)
2667 (arg-check string? message 'syntax-violation)
2668 (throw 'syntax-error who message
2669 (or (source-annotation subform)
2670 (source-annotation form))
2671 (strip form empty-wrap)
2672 (and subform (strip subform empty-wrap)))))
2673
2674 (let ()
2675 (define (syntax-module id)
2676 (arg-check nonsymbol-id? id 'syntax-module)
2677 (let ((mod (syntax-object-module id)))
2678 (and (not (equal? mod '(primitive)))
2679 (cdr mod))))
2680
2681 (define* (syntax-local-binding id #:key (resolve-syntax-parameters? #t))
2682 (arg-check nonsymbol-id? id 'syntax-local-binding)
2683 (with-transformer-environment
2684 (lambda (e r w s rib mod)
2685 (define (strip-anti-mark w)
2686 (let ((ms (wrap-marks w)) (s (wrap-subst w)))
2687 (if (and (pair? ms) (eq? (car ms) the-anti-mark))
2688 ;; output is from original text
2689 (make-wrap (cdr ms) (if rib (cons rib (cdr s)) (cdr s)))
2690 ;; output introduced by macro
2691 (make-wrap ms (if rib (cons rib s) s)))))
2692 (call-with-values (lambda ()
2693 (resolve-identifier
2694 (syntax-object-expression id)
2695 (strip-anti-mark (syntax-object-wrap id))
2696 r
2697 (syntax-object-module id)
2698 resolve-syntax-parameters?))
2699 (lambda (type value mod)
2700 (case type
2701 ((lexical) (values 'lexical value))
2702 ((macro) (values 'macro value))
2703 ((syntax-parameter) (values 'syntax-parameter (car value)))
2704 ((syntax) (values 'pattern-variable value))
2705 ((displaced-lexical) (values 'displaced-lexical #f))
2706 ((global)
2707 (if (equal? mod '(primitive))
2708 (values 'primitive value)
2709 (values 'global (cons value (cdr mod)))))
2710 (else (values 'other #f))))))))
2711
2712 (define (syntax-locally-bound-identifiers id)
2713 (arg-check nonsymbol-id? id 'syntax-locally-bound-identifiers)
2714 (locally-bound-identifiers (syntax-object-wrap id)
2715 (syntax-object-module id)))
2716
2717 ;; Using define! instead of set! to avoid warnings at
2718 ;; compile-time, after the variables are stolen away into (system
2719 ;; syntax). See the end of boot-9.scm.
2720 ;;
2721 (define! 'syntax-module syntax-module)
2722 (define! 'syntax-local-binding syntax-local-binding)
2723 (define! 'syntax-locally-bound-identifiers syntax-locally-bound-identifiers))
2724
2725 ;; $sc-dispatch expects an expression and a pattern. If the expression
2726 ;; matches the pattern a list of the matching expressions for each
2727 ;; "any" is returned. Otherwise, #f is returned. (This use of #f will
2728 ;; not work on r4rs implementations that violate the ieee requirement
2729 ;; that #f and () be distinct.)
2730
2731 ;; The expression is matched with the pattern as follows:
2732
2733 ;; pattern: matches:
2734 ;; () empty list
2735 ;; any anything
2736 ;; (<pattern>1 . <pattern>2) (<pattern>1 . <pattern>2)
2737 ;; each-any (any*)
2738 ;; #(free-id <key>) <key> with free-identifier=?
2739 ;; #(each <pattern>) (<pattern>*)
2740 ;; #(each+ p1 (p2_1 ... p2_n) p3) (p1* (p2_n ... p2_1) . p3)
2741 ;; #(vector <pattern>) (list->vector <pattern>)
2742 ;; #(atom <object>) <object> with "equal?"
2743
2744 ;; Vector cops out to pair under assumption that vectors are rare. If
2745 ;; not, should convert to:
2746 ;; #(vector <pattern>*) #(<pattern>*)
2747
2748 (let ()
2749
2750 (define match-each
2751 (lambda (e p w mod)
2752 (cond
2753 ((pair? e)
2754 (let ((first (match (car e) p w '() mod)))
2755 (and first
2756 (let ((rest (match-each (cdr e) p w mod)))
2757 (and rest (cons first rest))))))
2758 ((null? e) '())
2759 ((syntax-object? e)
2760 (match-each (syntax-object-expression e)
2761 p
2762 (join-wraps w (syntax-object-wrap e))
2763 (syntax-object-module e)))
2764 (else #f))))
2765
2766 (define match-each+
2767 (lambda (e x-pat y-pat z-pat w r mod)
2768 (let f ((e e) (w w))
2769 (cond
2770 ((pair? e)
2771 (call-with-values (lambda () (f (cdr e) w))
2772 (lambda (xr* y-pat r)
2773 (if r
2774 (if (null? y-pat)
2775 (let ((xr (match (car e) x-pat w '() mod)))
2776 (if xr
2777 (values (cons xr xr*) y-pat r)
2778 (values #f #f #f)))
2779 (values
2780 '()
2781 (cdr y-pat)
2782 (match (car e) (car y-pat) w r mod)))
2783 (values #f #f #f)))))
2784 ((syntax-object? e)
2785 (f (syntax-object-expression e) (join-wraps w e)))
2786 (else
2787 (values '() y-pat (match e z-pat w r mod)))))))
2788
2789 (define match-each-any
2790 (lambda (e w mod)
2791 (cond
2792 ((pair? e)
2793 (let ((l (match-each-any (cdr e) w mod)))
2794 (and l (cons (wrap (car e) w mod) l))))
2795 ((null? e) '())
2796 ((syntax-object? e)
2797 (match-each-any (syntax-object-expression e)
2798 (join-wraps w (syntax-object-wrap e))
2799 mod))
2800 (else #f))))
2801
2802 (define match-empty
2803 (lambda (p r)
2804 (cond
2805 ((null? p) r)
2806 ((eq? p '_) r)
2807 ((eq? p 'any) (cons '() r))
2808 ((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
2809 ((eq? p 'each-any) (cons '() r))
2810 (else
2811 (case (vector-ref p 0)
2812 ((each) (match-empty (vector-ref p 1) r))
2813 ((each+) (match-empty (vector-ref p 1)
2814 (match-empty
2815 (reverse (vector-ref p 2))
2816 (match-empty (vector-ref p 3) r))))
2817 ((free-id atom) r)
2818 ((vector) (match-empty (vector-ref p 1) r)))))))
2819
2820 (define combine
2821 (lambda (r* r)
2822 (if (null? (car r*))
2823 r
2824 (cons (map car r*) (combine (map cdr r*) r)))))
2825
2826 (define match*
2827 (lambda (e p w r mod)
2828 (cond
2829 ((null? p) (and (null? e) r))
2830 ((pair? p)
2831 (and (pair? e) (match (car e) (car p) w
2832 (match (cdr e) (cdr p) w r mod)
2833 mod)))
2834 ((eq? p 'each-any)
2835 (let ((l (match-each-any e w mod))) (and l (cons l r))))
2836 (else
2837 (case (vector-ref p 0)
2838 ((each)
2839 (if (null? e)
2840 (match-empty (vector-ref p 1) r)
2841 (let ((l (match-each e (vector-ref p 1) w mod)))
2842 (and l
2843 (let collect ((l l))
2844 (if (null? (car l))
2845 r
2846 (cons (map car l) (collect (map cdr l)))))))))
2847 ((each+)
2848 (call-with-values
2849 (lambda ()
2850 (match-each+ e (vector-ref p 1) (vector-ref p 2) (vector-ref p 3) w r mod))
2851 (lambda (xr* y-pat r)
2852 (and r
2853 (null? y-pat)
2854 (if (null? xr*)
2855 (match-empty (vector-ref p 1) r)
2856 (combine xr* r))))))
2857 ((free-id) (and (id? e) (free-id=? (wrap e w mod) (vector-ref p 1)) r))
2858 ((atom) (and (equal? (vector-ref p 1) (strip e w)) r))
2859 ((vector)
2860 (and (vector? e)
2861 (match (vector->list e) (vector-ref p 1) w r mod))))))))
2862
2863 (define match
2864 (lambda (e p w r mod)
2865 (cond
2866 ((not r) #f)
2867 ((eq? p '_) r)
2868 ((eq? p 'any) (cons (wrap e w mod) r))
2869 ((syntax-object? e)
2870 (match*
2871 (syntax-object-expression e)
2872 p
2873 (join-wraps w (syntax-object-wrap e))
2874 r
2875 (syntax-object-module e)))
2876 (else (match* e p w r mod)))))
2877
2878 (set! $sc-dispatch
2879 (lambda (e p)
2880 (cond
2881 ((eq? p 'any) (list e))
2882 ((eq? p '_) '())
2883 ((syntax-object? e)
2884 (match* (syntax-object-expression e)
2885 p (syntax-object-wrap e) '() (syntax-object-module e)))
2886 (else (match* e p empty-wrap '() #f))))))))
2887
2888
2889 (define-syntax with-syntax
2890 (lambda (x)
2891 (syntax-case x ()
2892 ((_ () e1 e2 ...)
2893 #'(let () e1 e2 ...))
2894 ((_ ((out in)) e1 e2 ...)
2895 #'(syntax-case in ()
2896 (out (let () e1 e2 ...))))
2897 ((_ ((out in) ...) e1 e2 ...)
2898 #'(syntax-case (list in ...) ()
2899 ((out ...) (let () e1 e2 ...)))))))
2900
2901 (define-syntax syntax-rules
2902 (lambda (xx)
2903 (syntax-case xx ()
2904 ((_ (k ...) ((keyword . pattern) template) ...)
2905 #'(lambda (x)
2906 ;; embed patterns as procedure metadata
2907 #((macro-type . syntax-rules)
2908 (patterns pattern ...))
2909 (syntax-case x (k ...)
2910 ((_ . pattern) #'template)
2911 ...)))
2912 ((_ (k ...) docstring ((keyword . pattern) template) ...)
2913 (string? (syntax->datum #'docstring))
2914 #'(lambda (x)
2915 ;; the same, but allow a docstring
2916 docstring
2917 #((macro-type . syntax-rules)
2918 (patterns pattern ...))
2919 (syntax-case x (k ...)
2920 ((_ . pattern) #'template)
2921 ...))))))
2922
2923 (define-syntax define-syntax-rule
2924 (lambda (x)
2925 (syntax-case x ()
2926 ((_ (name . pattern) template)
2927 #'(define-syntax name
2928 (syntax-rules ()
2929 ((_ . pattern) template))))
2930 ((_ (name . pattern) docstring template)
2931 (string? (syntax->datum #'docstring))
2932 #'(define-syntax name
2933 (syntax-rules ()
2934 docstring
2935 ((_ . pattern) template)))))))
2936
2937 (define-syntax let*
2938 (lambda (x)
2939 (syntax-case x ()
2940 ((let* ((x v) ...) e1 e2 ...)
2941 (and-map identifier? #'(x ...))
2942 (let f ((bindings #'((x v) ...)))
2943 (if (null? bindings)
2944 #'(let () e1 e2 ...)
2945 (with-syntax ((body (f (cdr bindings)))
2946 (binding (car bindings)))
2947 #'(let (binding) body))))))))
2948
2949 (define-syntax quasiquote
2950 (let ()
2951 (define (quasi p lev)
2952 (syntax-case p (unquote quasiquote)
2953 ((unquote p)
2954 (if (= lev 0)
2955 #'("value" p)
2956 (quasicons #'("quote" unquote) (quasi #'(p) (- lev 1)))))
2957 ((quasiquote p) (quasicons #'("quote" quasiquote) (quasi #'(p) (+ lev 1))))
2958 ((p . q)
2959 (syntax-case #'p (unquote unquote-splicing)
2960 ((unquote p ...)
2961 (if (= lev 0)
2962 (quasilist* #'(("value" p) ...) (quasi #'q lev))
2963 (quasicons
2964 (quasicons #'("quote" unquote) (quasi #'(p ...) (- lev 1)))
2965 (quasi #'q lev))))
2966 ((unquote-splicing p ...)
2967 (if (= lev 0)
2968 (quasiappend #'(("value" p) ...) (quasi #'q lev))
2969 (quasicons
2970 (quasicons #'("quote" unquote-splicing) (quasi #'(p ...) (- lev 1)))
2971 (quasi #'q lev))))
2972 (_ (quasicons (quasi #'p lev) (quasi #'q lev)))))
2973 (#(x ...) (quasivector (vquasi #'(x ...) lev)))
2974 (p #'("quote" p))))
2975 (define (vquasi p lev)
2976 (syntax-case p ()
2977 ((p . q)
2978 (syntax-case #'p (unquote unquote-splicing)
2979 ((unquote p ...)
2980 (if (= lev 0)
2981 (quasilist* #'(("value" p) ...) (vquasi #'q lev))
2982 (quasicons
2983 (quasicons #'("quote" unquote) (quasi #'(p ...) (- lev 1)))
2984 (vquasi #'q lev))))
2985 ((unquote-splicing p ...)
2986 (if (= lev 0)
2987 (quasiappend #'(("value" p) ...) (vquasi #'q lev))
2988 (quasicons
2989 (quasicons
2990 #'("quote" unquote-splicing)
2991 (quasi #'(p ...) (- lev 1)))
2992 (vquasi #'q lev))))
2993 (_ (quasicons (quasi #'p lev) (vquasi #'q lev)))))
2994 (() #'("quote" ()))))
2995 (define (quasicons x y)
2996 (with-syntax ((x x) (y y))
2997 (syntax-case #'y ()
2998 (("quote" dy)
2999 (syntax-case #'x ()
3000 (("quote" dx) #'("quote" (dx . dy)))
3001 (_ (if (null? #'dy) #'("list" x) #'("list*" x y)))))
3002 (("list" . stuff) #'("list" x . stuff))
3003 (("list*" . stuff) #'("list*" x . stuff))
3004 (_ #'("list*" x y)))))
3005 (define (quasiappend x y)
3006 (syntax-case y ()
3007 (("quote" ())
3008 (cond
3009 ((null? x) #'("quote" ()))
3010 ((null? (cdr x)) (car x))
3011 (else (with-syntax (((p ...) x)) #'("append" p ...)))))
3012 (_
3013 (cond
3014 ((null? x) y)
3015 (else (with-syntax (((p ...) x) (y y)) #'("append" p ... y)))))))
3016 (define (quasilist* x y)
3017 (let f ((x x))
3018 (if (null? x)
3019 y
3020 (quasicons (car x) (f (cdr x))))))
3021 (define (quasivector x)
3022 (syntax-case x ()
3023 (("quote" (x ...)) #'("quote" #(x ...)))
3024 (_
3025 (let f ((y x) (k (lambda (ls) #`("vector" #,@ls))))
3026 (syntax-case y ()
3027 (("quote" (y ...)) (k #'(("quote" y) ...)))
3028 (("list" y ...) (k #'(y ...)))
3029 (("list*" y ... z) (f #'z (lambda (ls) (k (append #'(y ...) ls)))))
3030 (else #`("list->vector" #,x)))))))
3031 (define (emit x)
3032 (syntax-case x ()
3033 (("quote" x) #''x)
3034 (("list" x ...) #`(list #,@(map emit #'(x ...))))
3035 ;; could emit list* for 3+ arguments if implementation supports
3036 ;; list*
3037 (("list*" x ... y)
3038 (let f ((x* #'(x ...)))
3039 (if (null? x*)
3040 (emit #'y)
3041 #`(cons #,(emit (car x*)) #,(f (cdr x*))))))
3042 (("append" x ...) #`(append #,@(map emit #'(x ...))))
3043 (("vector" x ...) #`(vector #,@(map emit #'(x ...))))
3044 (("list->vector" x) #`(list->vector #,(emit #'x)))
3045 (("value" x) #'x)))
3046 (lambda (x)
3047 (syntax-case x ()
3048 ;; convert to intermediate language, combining introduced (but
3049 ;; not unquoted source) quote expressions where possible and
3050 ;; choosing optimal construction code otherwise, then emit
3051 ;; Scheme code corresponding to the intermediate language forms.
3052 ((_ e) (emit (quasi #'e 0)))))))
3053
3054 (define-syntax include
3055 (lambda (x)
3056 (define read-file
3057 (lambda (fn dir k)
3058 (let* ((p (open-input-file
3059 (if (absolute-file-name? fn)
3060 fn
3061 (in-vicinity dir fn))))
3062 (enc (file-encoding p)))
3063
3064 ;; Choose the input encoding deterministically.
3065 (set-port-encoding! p (or enc "UTF-8"))
3066
3067 (let f ((x (read p))
3068 (result '()))
3069 (if (eof-object? x)
3070 (begin
3071 (close-input-port p)
3072 (reverse result))
3073 (f (read p)
3074 (cons (datum->syntax k x) result)))))))
3075 (let* ((src (syntax-source x))
3076 (file (and src (assq-ref src 'filename)))
3077 (dir (and (string? file) (dirname file))))
3078 (syntax-case x ()
3079 ((k filename)
3080 (let ((fn (syntax->datum #'filename)))
3081 (with-syntax (((exp ...) (read-file fn dir #'filename)))
3082 #'(begin exp ...))))))))
3083
3084 (define-syntax include-from-path
3085 (lambda (x)
3086 (syntax-case x ()
3087 ((k filename)
3088 (let ((fn (syntax->datum #'filename)))
3089 (with-syntax ((fn (datum->syntax
3090 #'filename
3091 (or (%search-load-path fn)
3092 (syntax-violation 'include-from-path
3093 "file not found in path"
3094 x #'filename)))))
3095 #'(include fn)))))))
3096
3097 (define-syntax unquote
3098 (lambda (x)
3099 (syntax-violation 'unquote
3100 "expression not valid outside of quasiquote"
3101 x)))
3102
3103 (define-syntax unquote-splicing
3104 (lambda (x)
3105 (syntax-violation 'unquote-splicing
3106 "expression not valid outside of quasiquote"
3107 x)))
3108
3109 (define (make-variable-transformer proc)
3110 (if (procedure? proc)
3111 (let ((trans (lambda (x)
3112 #((macro-type . variable-transformer))
3113 (proc x))))
3114 (set-procedure-property! trans 'variable-transformer #t)
3115 trans)
3116 (error "variable transformer not a procedure" proc)))
3117
3118 (define-syntax identifier-syntax
3119 (lambda (xx)
3120 (syntax-case xx (set!)
3121 ((_ e)
3122 #'(lambda (x)
3123 #((macro-type . identifier-syntax))
3124 (syntax-case x ()
3125 (id
3126 (identifier? #'id)
3127 #'e)
3128 ((_ x (... ...))
3129 #'(e x (... ...))))))
3130 ((_ (id exp1) ((set! var val) exp2))
3131 (and (identifier? #'id) (identifier? #'var))
3132 #'(make-variable-transformer
3133 (lambda (x)
3134 #((macro-type . variable-transformer))
3135 (syntax-case x (set!)
3136 ((set! var val) #'exp2)
3137 ((id x (... ...)) #'(exp1 x (... ...)))
3138 (id (identifier? #'id) #'exp1))))))))
3139
3140 (define-syntax define*
3141 (lambda (x)
3142 (syntax-case x ()
3143 ((_ (id . args) b0 b1 ...)
3144 #'(define id (lambda* args b0 b1 ...)))
3145 ((_ id val) (identifier? #'id)
3146 #'(define id val)))))