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