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