3 ;;;; Copyright (C) 2001 Free Software Foundation, Inc.
5 ;;;; This program is free software; you can redistribute it and/or modify
6 ;;;; it under the terms of the GNU General Public License as published by
7 ;;;; the Free Software Foundation; either version 2, or (at your option)
8 ;;;; any later version.
10 ;;;; This program is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;;;; GNU General Public License for more details.
15 ;;;; You should have received a copy of the GNU General Public License
16 ;;;; along with this software; see the file COPYING. If not, write to
17 ;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 ;;;; Boston, MA 02111-1307 USA
20 ;;;; As a special exception, the Free Software Foundation gives permission
21 ;;;; for additional uses of the text contained in its release of GUILE.
23 ;;;; The exception is that, if you link the GUILE library with other files
24 ;;;; to produce an executable, this does not by itself cause the
25 ;;;; resulting executable to be covered by the GNU General Public License.
26 ;;;; Your use of that executable is in no way restricted on account of
27 ;;;; linking the GUILE library code into it.
29 ;;;; This exception does not however invalidate any other reasons why
30 ;;;; the executable file might be covered by the GNU General Public License.
32 ;;;; This exception applies only to the code released by the
33 ;;;; Free Software Foundation under the name GUILE. If you copy
34 ;;;; code from other Free Software Foundation releases into a copy of
35 ;;;; GUILE, as the General Public License permits, the exception does
36 ;;;; not apply to the code that you add in this way. To avoid misleading
37 ;;;; anyone as to the status of such modified files, you must delete
38 ;;;; this exception notice from them.
40 ;;;; If you write modifications of your own for GUILE, it is your choice
41 ;;;; whether to permit this exception to apply to your modifications.
42 ;;;; If you do not wish that, delete this exception notice.
46 ;;; Portable implementation of syntax-case
47 ;;; Extracted from Chez Scheme Version 5.9f
48 ;;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman
50 ;;; Modified by Mikael Djurfeldt <djurfeldt@nada.kth.se> according
51 ;;; to the ChangeLog distributed in the same directory as this file:
52 ;;; 1997-08-19, 1997-09-03, 1997-09-10, 2000-08-13, 2000-08-24,
53 ;;; 2000-09-12, 2001-03-08
55 ;;; Copyright (c) 1992-1997 Cadence Research Systems
56 ;;; Permission to copy this software, in whole or in part, to use this
57 ;;; software for any lawful purpose, and to redistribute this software
58 ;;; is granted subject to the restriction that all copies made of this
59 ;;; software must include this copyright notice in full. This software
60 ;;; is provided AS IS, with NO WARRANTY, EITHER EXPRESS OR IMPLIED,
61 ;;; INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
62 ;;; OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE
63 ;;; AUTHORS BE LIABLE FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES OF ANY
64 ;;; NATURE WHATSOEVER.
66 ;;; Before attempting to port this code to a new implementation of
67 ;;; Scheme, please read the notes below carefully.
70 ;;; This file defines the syntax-case expander, sc-expand, and a set
71 ;;; of associated syntactic forms and procedures. Of these, the
72 ;;; following are documented in The Scheme Programming Language,
73 ;;; Second Edition (R. Kent Dybvig, Prentice Hall, 1996). Most are
74 ;;; also documented in the R4RS and draft R5RS.
76 ;;; bound-identifier=?
77 ;;; datum->syntax-object
81 ;;; generate-temporaries
88 ;;; syntax-object->datum
92 ;;; All standard Scheme syntactic forms are supported by the expander
93 ;;; or syntactic abstractions defined in this file. Only the R4RS
94 ;;; delay is omitted, since its expansion is implementation-dependent.
96 ;;; The remaining exports are listed below:
99 ;;; if datum represents a valid expression, sc-expand returns an
100 ;;; expanded version of datum in a core language that includes no
101 ;;; syntactic abstractions. The core language includes begin,
102 ;;; define, if, lambda, letrec, quote, and set!.
103 ;;; (eval-when situations expr ...)
104 ;;; conditionally evaluates expr ... at compile-time or run-time
105 ;;; depending upon situations (see the Chez Scheme System Manual,
106 ;;; Revision 3, for a complete description)
107 ;;; (syntax-error object message)
108 ;;; used to report errors found during expansion
109 ;;; (install-global-transformer symbol value)
110 ;;; used by expanded code to install top-level syntactic abstractions
111 ;;; (syntax-dispatch e p)
112 ;;; used by expanded code to handle syntax-case matching
114 ;;; The following nonstandard procedures must be provided by the
115 ;;; implementation for this code to run.
118 ;;; returns the implementation's cannonical "unspecified value". This
119 ;;; usually works: (define void (lambda () (if #f #f))).
121 ;;; (andmap proc list1 list2 ...)
122 ;;; returns true if proc returns true when applied to each element of list1
123 ;;; along with the corresponding elements of list2 ....
124 ;;; The following definition works but does no error checking:
127 ;;; (lambda (f first . rest)
128 ;;; (or (null? first)
130 ;;; (let andmap ((first first))
131 ;;; (let ((x (car first)) (first (cdr first)))
132 ;;; (if (null? first)
134 ;;; (and (f x) (andmap first)))))
135 ;;; (let andmap ((first first) (rest rest))
136 ;;; (let ((x (car first))
137 ;;; (xr (map car rest))
138 ;;; (first (cdr first))
139 ;;; (rest (map cdr rest)))
140 ;;; (if (null? first)
141 ;;; (apply f (cons x xr))
142 ;;; (and (apply f (cons x xr)) (andmap first rest)))))))))
144 ;;; The following nonstandard procedures must also be provided by the
145 ;;; implementation for this code to run using the standard portable
146 ;;; hooks and output constructors. They are not used by expanded code,
147 ;;; and so need be present only at expansion time.
150 ;;; where x is always in the form ("noexpand" expr).
151 ;;; returns the value of expr. the "noexpand" flag is used to tell the
152 ;;; evaluator/expander that no expansion is necessary, since expr has
153 ;;; already been fully expanded to core forms.
155 ;;; eval will not be invoked during the loading of psyntax.pp. After
156 ;;; psyntax.pp has been loaded, the expansion of any macro definition,
157 ;;; whether local or global, will result in a call to eval. If, however,
158 ;;; sc-expand has already been registered as the expander to be used
159 ;;; by eval, and eval accepts one argument, nothing special must be done
160 ;;; to support the "noexpand" flag, since it is handled by sc-expand.
162 ;;; (error who format-string why what)
163 ;;; where who is either a symbol or #f, format-string is always "~a ~s",
164 ;;; why is always a string, and what may be any object. error should
165 ;;; signal an error with a message something like
167 ;;; "error in <who>: <why> <what>"
170 ;;; returns a unique symbol each time it's called
172 ;;; (putprop symbol key value)
173 ;;; (getprop symbol key)
174 ;;; key is always the symbol *sc-expander*; value may be any object.
175 ;;; putprop should associate the given value with the given symbol in
176 ;;; some way that it can be retrieved later with getprop.
178 ;;; When porting to a new Scheme implementation, you should define the
179 ;;; procedures listed above, load the expanded version of psyntax.ss
180 ;;; (psyntax.pp, which should be available whereever you found
181 ;;; psyntax.ss), and register sc-expand as the current expander (how
182 ;;; you do this depends upon your implementation of Scheme). You may
183 ;;; change the hooks and constructors defined toward the beginning of
184 ;;; the code below, but to avoid bootstrapping problems, do so only
185 ;;; after you have a working version of the expander.
187 ;;; Chez Scheme allows the syntactic form (syntax <template>) to be
188 ;;; abbreviated to #'<template>, just as (quote <datum>) may be
189 ;;; abbreviated to '<datum>. The #' syntax makes programs written
190 ;;; using syntax-case shorter and more readable and draws out the
191 ;;; intuitive connection between syntax and quote.
193 ;;; If you find that this code loads or runs slowly, consider
194 ;;; switching to faster hardware or a faster implementation of
195 ;;; Scheme. In Chez Scheme on a 200Mhz Pentium Pro, expanding,
196 ;;; compiling (with full optimization), and loading this file takes
197 ;;; between one and two seconds.
199 ;;; In the expander implementation, we sometimes use syntactic abstractions
200 ;;; when procedural abstractions would suffice. For example, we define
201 ;;; top-wrap and top-marked? as
202 ;;; (define-syntax top-wrap (identifier-syntax '((top))))
203 ;;; (define-syntax top-marked?
205 ;;; ((_ w) (memq 'top (wrap-marks w)))))
207 ;;; (define top-wrap '((top)))
208 ;;; (define top-marked?
209 ;;; (lambda (w) (memq 'top (wrap-marks w))))
210 ;;; On ther other hand, we don't do this consistently; we define make-wrap,
211 ;;; wrap-marks, and wrap-subst simply as
212 ;;; (define make-wrap cons)
213 ;;; (define wrap-marks car)
214 ;;; (define wrap-subst cdr)
215 ;;; In Chez Scheme, the syntactic and procedural forms of these
216 ;;; abstractions are equivalent, since the optimizer consistently
217 ;;; integrates constants and small procedures. Some Scheme
218 ;;; implementations, however, may benefit from more consistent use
219 ;;; of one form or the other.
222 ;;; implementation information:
224 ;;; "begin" is treated as a splicing construct at top level and at
225 ;;; the beginning of bodies. Any sequence of expressions that would
226 ;;; be allowed where the "begin" occurs is allowed.
228 ;;; "let-syntax" and "letrec-syntax" are also treated as splicing
229 ;;; constructs, in violation of the R4RS appendix and probably the R5RS
230 ;;; when it comes out. A consequence, let-syntax and letrec-syntax do
231 ;;; not create local contours, as do let and letrec. Although the
232 ;;; functionality is greater as it is presently implemented, we will
233 ;;; probably change it to conform to the R4RS/expected R5RS.
235 ;;; Objects with no standard print syntax, including objects containing
236 ;;; cycles and syntax object, are allowed in quoted data as long as they
237 ;;; are contained within a syntax form or produced by datum->syntax-object.
238 ;;; Such objects are never copied.
240 ;;; All identifiers that don't have macro definitions and are not bound
241 ;;; lexically are assumed to be global variables
243 ;;; Top-level definitions of macro-introduced identifiers are allowed.
244 ;;; This may not be appropriate for implementations in which the
245 ;;; model is that bindings are created by definitions, as opposed to
246 ;;; one in which initial values are assigned by definitions.
248 ;;; Top-level variable definitions of syntax keywords is not permitted.
249 ;;; Any solution allowing this would be kludgey and would yield
250 ;;; surprising results in some cases. We can provide an undefine-syntax
251 ;;; form. The questions is, should define be an implicit undefine-syntax?
252 ;;; We've decided no for now.
254 ;;; Identifiers and syntax objects are implemented as vectors for
255 ;;; portability. As a result, it is possible to "forge" syntax
258 ;;; The implementation of generate-temporaries assumes that it is possible
259 ;;; to generate globally unique symbols (gensyms).
261 ;;; The input to sc-expand may contain "annotations" describing, e.g., the
262 ;;; source file and character position from where each object was read if
263 ;;; it was read from a file. These annotations are handled properly by
264 ;;; sc-expand only if the annotation? hook (see hooks below) is implemented
265 ;;; properly and the operators make-annotation, annotation-expression,
266 ;;; annotation-source, annotation-stripped, and set-annotation-stripped!
267 ;;; are supplied. If annotations are supplied, the proper annotation
268 ;;; source is passed to the various output constructors, allowing
269 ;;; implementations to accurately correlate source and expanded code.
270 ;;; Contact one of the authors for details if you wish to make use of
277 ;;; When changing syntax-object representations, it is necessary to support
278 ;;; both old and new syntax-object representations in id-var-name. It
279 ;;; should be sufficient to recognize old representations and treat
280 ;;; them as not lexically bound.
285 (define-syntax define-structure
287 (define construct-name
288 (lambda (template-identifier . args)
289 (datum->syntax-object
296 (symbol->string (syntax-object->datum x))))
300 (andmap identifier? (syntax (name id1 ...)))
302 ((constructor (construct-name (syntax name) "make-" (syntax name)))
303 (predicate (construct-name (syntax name) (syntax name) "?"))
305 (map (lambda (x) (construct-name x (syntax name) "-" x))
309 (construct-name x "set-" (syntax name) "-" x "!"))
312 (+ (length (syntax (id1 ...))) 1))
314 (let f ((i 1) (ids (syntax (id1 ...))))
317 (cons i (f (+ i 1) (cdr ids)))))))
321 (vector 'name id1 ... )))
325 (= (vector-length x) structure-length)
326 (eq? (vector-ref x 0) 'name))))
329 (vector-ref x index)))
333 (vector-set! x index update)))
337 (define noexpand "noexpand")
339 ;;; hooks to nonportable run-time helpers
346 (define annotation? (lambda (x) #f))
348 (define top-level-eval-hook
350 (eval `(,noexpand ,x) (interaction-environment))))
352 (define local-eval-hook
354 (eval `(,noexpand ,x) (interaction-environment))))
357 (lambda (who why what)
358 (error who "~a ~s" why what)))
360 (define-syntax gensym-hook
364 (define put-global-definition-hook
365 (lambda (symbol binding)
366 (putprop symbol '*sc-expander* binding)))
368 (define get-global-definition-hook
370 (getprop symbol '*sc-expander*)))
374 ;;; output constructors
376 (define-syntax build-application
378 ((_ source fun-exp arg-exps)
379 `(,fun-exp . ,arg-exps))))
381 (define-syntax build-conditional
383 ((_ source test-exp then-exp else-exp)
384 `(if ,test-exp ,then-exp ,else-exp))))
386 (define-syntax build-lexical-reference
391 (define-syntax build-lexical-assignment
396 (define-syntax build-global-reference
401 (define-syntax build-global-assignment
406 (define-syntax build-global-definition
409 `(define ,var ,exp))))
411 (define-syntax build-lambda
414 `(lambda ,vars ,exp))))
416 (define-syntax build-primref
419 ((_ src level name) name)))
421 (define-syntax build-data
423 ((_ src exp) `',exp)))
425 (define build-sequence
427 (if (null? (cdr exps))
432 (lambda (src vars val-exps body-exp)
435 `(let ,(map list vars val-exps) ,body-exp))))
437 (define build-named-let
438 (lambda (src vars val-exps body-exp)
441 `(let ,(car vars) ,(map list (cdr vars) val-exps) ,body-exp))))
444 (lambda (src vars val-exps body-exp)
447 `(letrec ,(map list vars val-exps) ,body-exp))))
449 (define-syntax build-lexical-var
451 ((_ src id) (gensym (symbol->string id)))))
453 (define-syntax self-evaluating?
457 (or (boolean? x) (number? x) (string? x) (char? x) (null? x) (keyword? x))))))
460 (define-structure (syntax-object expression wrap))
462 (define-syntax unannotate
467 (annotation-expression e)
470 (define-syntax no-source (identifier-syntax #f))
472 (define source-annotation
475 ((annotation? x) (annotation-source x))
476 ((syntax-object? x) (source-annotation (syntax-object-expression x)))
479 (define-syntax arg-check
483 (if (not (pred? x)) (error-hook who "invalid argument" x))))))
485 ;;; compile-time environments
487 ;;; wrap and environment comprise two level mapping.
488 ;;; wrap : id --> label
489 ;;; env : label --> <element>
491 ;;; environments are represented in two parts: a lexical part and a global
492 ;;; part. The lexical part is a simple list of associations from labels
493 ;;; to bindings. The global part is implemented by
494 ;;; {put,get}-global-definition-hook and associates symbols with
497 ;;; global (assumed global variable) and displaced-lexical (see below)
498 ;;; do not show up in any environment; instead, they are fabricated by
499 ;;; lookup when it finds no other bindings.
501 ;;; <environment> ::= ((<label> . <binding>)*)
503 ;;; identifier bindings include a type and a value
505 ;;; <binding> ::= (macro . <procedure>) macros
506 ;;; (core . <procedure>) core forms
509 ;;; (define-syntax) define-syntax
510 ;;; (local-syntax . rec?) let-syntax/letrec-syntax
511 ;;; (eval-when) eval-when
512 ;;; (syntax . (<var> . <level>)) pattern variables
513 ;;; (global) assumed global variable
514 ;;; (lexical . <var>) lexical variables
515 ;;; (displaced-lexical) displaced lexicals
516 ;;; <level> ::= <nonnegative integer>
517 ;;; <var> ::= variable returned by build-lexical-var
519 ;;; a macro is a user-defined syntactic-form. a core is a system-defined
520 ;;; syntactic form. begin, define, define-syntax, and eval-when are
521 ;;; treated specially since they are sensitive to whether the form is
522 ;;; at top-level and (except for eval-when) can denote valid internal
525 ;;; a pattern variable is a variable introduced by syntax-case and can
526 ;;; be referenced only within a syntax form.
528 ;;; any identifier for which no top-level syntax definition or local
529 ;;; binding of any kind has been seen is assumed to be a global
532 ;;; a lexical variable is a lambda- or letrec-bound variable.
534 ;;; a displaced-lexical identifier is a lexical identifier removed from
535 ;;; it's scope by the return of a syntax object containing the identifier.
536 ;;; a displaced lexical can also appear when a letrec-syntax-bound
537 ;;; keyword is referenced on the rhs of one of the letrec-syntax clauses.
538 ;;; a displaced lexical should never occur with properly written macros.
540 (define-syntax make-binding
541 (syntax-rules (quote)
542 ((_ type value) (cons type value))
544 ((_ type) (cons type '()))))
545 (define binding-type car)
546 (define binding-value cdr)
548 (define-syntax null-env (identifier-syntax '()))
551 (lambda (labels bindings r)
554 (extend-env (cdr labels) (cdr bindings)
555 (cons (cons (car labels) (car bindings)) r)))))
557 (define extend-var-env
558 ; variant of extend-env that forms "lexical" binding
559 (lambda (labels vars r)
562 (extend-var-env (cdr labels) (cdr vars)
563 (cons (cons (car labels) (make-binding 'lexical (car vars))) r)))))
565 ;;; we use a "macros only" environment in expansion of local macro
566 ;;; definitions so that their definitions can use local macros without
567 ;;; attempting to use other lexical identifiers.
568 (define macros-only-env
573 (if (eq? (cadr a) 'macro)
574 (cons a (macros-only-env (cdr r)))
575 (macros-only-env (cdr r)))))))
578 ; x may be a label or a symbol
579 ; although symbols are usually global, we check the environment first
580 ; anyway because a temporary binding may have been established by
586 (or (get-global-definition-hook x) (make-binding 'global)))
587 (else (make-binding 'displaced-lexical)))))
589 (define global-extend
590 (lambda (type sym val)
591 (put-global-definition-hook sym (make-binding type val))))
594 ;;; Conceptually, identifiers are always syntax objects. Internally,
595 ;;; however, the wrap is sometimes maintained separately (a source of
596 ;;; efficiency and confusion), so that symbols are also considered
597 ;;; identifiers by id?. Externally, they are always wrapped.
599 (define nonsymbol-id?
601 (and (syntax-object? x)
602 (symbol? (unannotate (syntax-object-expression x))))))
608 ((syntax-object? x) (symbol? (unannotate (syntax-object-expression x))))
609 ((annotation? x) (symbol? (annotation-expression x)))
612 (define-syntax id-sym-name
616 (unannotate (if (syntax-object? x) (syntax-object-expression x) x))))))
618 (define id-sym-name&marks
620 (if (syntax-object? x)
622 (unannotate (syntax-object-expression x))
623 (join-marks (wrap-marks w) (wrap-marks (syntax-object-wrap x))))
624 (values (unannotate x) (wrap-marks w)))))
626 ;;; syntax object wraps
628 ;;; <wrap> ::= ((<mark> ...) . (<subst> ...))
629 ;;; <subst> ::= <shift> | <subs>
630 ;;; <subs> ::= #(<old name> <label> (<mark> ...))
631 ;;; <shift> ::= positive fixnum
633 (define make-wrap cons)
634 (define wrap-marks car)
635 (define wrap-subst cdr)
637 (define-syntax subst-rename? (identifier-syntax vector?))
638 (define-syntax rename-old (syntax-rules () ((_ x) (vector-ref x 0))))
639 (define-syntax rename-new (syntax-rules () ((_ x) (vector-ref x 1))))
640 (define-syntax rename-marks (syntax-rules () ((_ x) (vector-ref x 2))))
641 (define-syntax make-rename
643 ((_ old new marks) (vector old new marks))))
645 ;;; labels must be comparable with "eq?" and distinct from symbols.
647 (lambda () (string #\i)))
653 (cons (gen-label) (gen-labels (cdr ls))))))
655 (define-structure (ribcage symnames marks labels))
657 (define-syntax empty-wrap (identifier-syntax '(())))
659 (define-syntax top-wrap (identifier-syntax '((top))))
661 (define-syntax top-marked?
663 ((_ w) (memq 'top (wrap-marks w)))))
665 ;;; Marks must be comparable with "eq?" and distinct from pairs and
666 ;;; the symbol top. We do not use integers so that marks will remain
667 ;;; unique even across file compiles.
669 (define-syntax the-anti-mark (identifier-syntax #f))
673 (make-wrap (cons the-anti-mark (wrap-marks w))
674 (cons 'shift (wrap-subst w)))))
676 (define-syntax new-mark
680 ;;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
681 ;;; internal definitions, in which the ribcages are built incrementally
682 (define-syntax make-empty-ribcage
684 ((_) (make-ribcage '() '() '()))))
686 (define extend-ribcage!
687 ; must receive ids with complete wraps
688 (lambda (ribcage id label)
689 (set-ribcage-symnames! ribcage
690 (cons (unannotate (syntax-object-expression id))
691 (ribcage-symnames ribcage)))
692 (set-ribcage-marks! ribcage
693 (cons (wrap-marks (syntax-object-wrap id))
694 (ribcage-marks ribcage)))
695 (set-ribcage-labels! ribcage
696 (cons label (ribcage-labels ribcage)))))
698 ;;; make-binding-wrap creates vector-based ribcages
699 (define make-binding-wrap
700 (lambda (ids labels w)
706 (let ((labelvec (list->vector labels)))
707 (let ((n (vector-length labelvec)))
708 (let ((symnamevec (make-vector n)) (marksvec (make-vector n)))
709 (let f ((ids ids) (i 0))
710 (if (not (null? ids))
712 (lambda () (id-sym-name&marks (car ids) w))
713 (lambda (symname marks)
714 (vector-set! symnamevec i symname)
715 (vector-set! marksvec i marks)
716 (f (cdr ids) (fx+ i 1))))))
717 (make-ribcage symnamevec marksvec labelvec))))
728 (let ((m1 (wrap-marks w1)) (s1 (wrap-subst w1)))
734 (smart-append s1 (wrap-subst w2))))
736 (smart-append m1 (wrap-marks w2))
737 (smart-append s1 (wrap-subst w2)))))))
741 (smart-append m1 m2)))
748 (eq? (car x) (car y))
749 (same-marks? (cdr x) (cdr y))))))
755 ((_ e) (call-with-values (lambda () e) (lambda (x . ignore) x)))))
757 (lambda (sym subst marks)
760 (let ((fst (car subst)))
762 (search sym (cdr subst) (cdr marks))
763 (let ((symnames (ribcage-symnames fst)))
764 (if (vector? symnames)
765 (search-vector-rib sym subst marks symnames fst)
766 (search-list-rib sym subst marks symnames fst))))))))
767 (define search-list-rib
768 (lambda (sym subst marks symnames ribcage)
769 (let f ((symnames symnames) (i 0))
771 ((null? symnames) (search sym (cdr subst) marks))
772 ((and (eq? (car symnames) sym)
773 (same-marks? marks (list-ref (ribcage-marks ribcage) i)))
774 (values (list-ref (ribcage-labels ribcage) i) marks))
775 (else (f (cdr symnames) (fx+ i 1)))))))
776 (define search-vector-rib
777 (lambda (sym subst marks symnames ribcage)
778 (let ((n (vector-length symnames)))
781 ((fx= i n) (search sym (cdr subst) marks))
782 ((and (eq? (vector-ref symnames i) sym)
783 (same-marks? marks (vector-ref (ribcage-marks ribcage) i)))
784 (values (vector-ref (ribcage-labels ribcage) i) marks))
785 (else (f (fx+ i 1))))))))
788 (or (first (search id (wrap-subst w) (wrap-marks w))) id))
790 (let ((id (unannotate (syntax-object-expression id)))
791 (w1 (syntax-object-wrap id)))
792 (let ((marks (join-marks (wrap-marks w) (wrap-marks w1))))
793 (call-with-values (lambda () (search id (wrap-subst w) marks))
794 (lambda (new-id marks)
796 (first (search id (wrap-subst w1) marks))
799 (let ((id (unannotate id)))
800 (or (first (search id (wrap-subst w) (wrap-marks w))) id)))
801 (else (error-hook 'id-var-name "invalid id" id)))))
803 ;;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
804 ;;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
808 (and (eq? (id-sym-name i) (id-sym-name j)) ; accelerator
809 (eq? (id-var-name i empty-wrap) (id-var-name j empty-wrap)))))
811 ;;; bound-id=? may be passed unwrapped (or partially wrapped) ids as
812 ;;; long as the missing portion of the wrap is common to both of the ids
813 ;;; since (bound-id=? x y) iff (bound-id=? (wrap x w) (wrap y w))
817 (if (and (syntax-object? i) (syntax-object? j))
818 (and (eq? (unannotate (syntax-object-expression i))
819 (unannotate (syntax-object-expression j)))
820 (same-marks? (wrap-marks (syntax-object-wrap i))
821 (wrap-marks (syntax-object-wrap j))))
822 (eq? (unannotate i) (unannotate j)))))
824 ;;; "valid-bound-ids?" returns #t if it receives a list of distinct ids.
825 ;;; valid-bound-ids? may be passed unwrapped (or partially wrapped) ids
826 ;;; as long as the missing portion of the wrap is common to all of the
829 (define valid-bound-ids?
831 (and (let all-ids? ((ids ids))
834 (all-ids? (cdr ids)))))
835 (distinct-bound-ids? ids))))
837 ;;; distinct-bound-ids? expects a list of ids and returns #t if there are
838 ;;; no duplicates. It is quadratic on the length of the id list; long
839 ;;; lists could be sorted to make it more efficient. distinct-bound-ids?
840 ;;; may be passed unwrapped (or partially wrapped) ids as long as the
841 ;;; missing portion of the wrap is common to all of the ids.
843 (define distinct-bound-ids?
845 (let distinct? ((ids ids))
847 (and (not (bound-id-member? (car ids) (cdr ids)))
848 (distinct? (cdr ids)))))))
850 (define bound-id-member?
852 (and (not (null? list))
853 (or (bound-id=? x (car list))
854 (bound-id-member? x (cdr list))))))
856 ;;; wrapping expressions and identifiers
861 ((and (null? (wrap-marks w)) (null? (wrap-subst w))) x)
864 (syntax-object-expression x)
865 (join-wraps w (syntax-object-wrap x))))
867 (else (make-syntax-object x w)))))
871 (wrap (if s (make-annotation x s #f) x) w)))
878 (let dobody ((body body) (r r) (w w))
881 (let ((first (chi (car body) r w)))
882 (cons first (dobody (cdr body) r w))))))))
884 (define chi-top-sequence
885 (lambda (body r w s m esew)
887 (let dobody ((body body) (r r) (w w) (m m) (esew esew))
890 (let ((first (chi-top (car body) r w m esew)))
891 (cons first (dobody (cdr body) r w m esew))))))))
893 (define chi-install-global
895 (build-application no-source
896 (build-primref no-source 'install-global-transformer)
897 (list (build-data no-source name) e))))
899 (define chi-when-list
900 (lambda (e when-list w)
901 ; when-list is syntax'd version of list of situations
902 (let f ((when-list when-list) (situations '()))
903 (if (null? when-list)
906 (cons (let ((x (car when-list)))
908 ((free-id=? x (syntax compile)) 'compile)
909 ((free-id=? x (syntax load)) 'load)
910 ((free-id=? x (syntax eval)) 'eval)
911 (else (syntax-error (wrap x w)
912 "invalid eval-when situation"))))
915 ;;; syntax-type returns five values: type, value, e, w, and s. The first
916 ;;; two are described in the table below.
918 ;;; type value explanation
919 ;;; -------------------------------------------------------------------
920 ;;; core procedure core form (including singleton)
921 ;;; lexical name lexical variable reference
922 ;;; global name global variable reference
923 ;;; begin none begin keyword
924 ;;; define none define keyword
925 ;;; define-syntax none define-syntax keyword
926 ;;; local-syntax rec? letrec-syntax/let-syntax keyword
927 ;;; eval-when none eval-when keyword
928 ;;; syntax level pattern variable
929 ;;; displaced-lexical none displaced lexical identifier
930 ;;; lexical-call name call to lexical variable
931 ;;; global-call name call to global variable
932 ;;; call none any other call
933 ;;; begin-form none begin expression
934 ;;; define-form id variable definition
935 ;;; define-syntax-form id syntax definition
936 ;;; local-syntax-form rec? syntax definition
937 ;;; eval-when-form none eval-when form
938 ;;; constant none self-evaluating datum
939 ;;; other none anything else
941 ;;; For define-form and define-syntax-form, e is the rhs expression.
942 ;;; For all others, e is the entire form. w is the wrap for e.
943 ;;; s is the source for the entire form.
945 ;;; syntax-type expands macros and unwraps as necessary to get to
946 ;;; one of the forms above. It also parses define and define-syntax
947 ;;; forms, although perhaps this should be done by the consumer.
950 (lambda (e r w s rib)
953 (let* ((n (id-var-name e w))
955 (type (binding-type b)))
957 ((lexical) (values type (binding-value b) e w s))
958 ((global) (values type n e w s))
960 (syntax-type (chi-macro (binding-value b) e r w rib) r empty-wrap s rib))
961 (else (values type (binding-value b) e w s)))))
963 (let ((first (car e)))
965 (let* ((n (id-var-name first w))
967 (type (binding-type b)))
969 ((lexical) (values 'lexical-call (binding-value b) e w s))
970 ((global) (values 'global-call n e w s))
972 (syntax-type (chi-macro (binding-value b) e r w rib)
974 ((core) (values type (binding-value b) e w s))
976 (values 'local-syntax-form (binding-value b) e w s))
977 ((begin) (values 'begin-form #f e w s))
978 ((eval-when) (values 'eval-when-form #f e w s))
983 (values 'define-form (syntax name) (syntax val) w s))
984 ((_ (name . args) e1 e2 ...)
985 (and (id? (syntax name))
986 (valid-bound-ids? (lambda-var-list (syntax args))))
987 ; need lambda here...
988 (values 'define-form (wrap (syntax name) w)
989 (cons (syntax lambda) (wrap (syntax (args e1 e2 ...)) w))
993 (values 'define-form (wrap (syntax name) w)
1000 (values 'define-syntax-form (syntax name)
1001 (syntax val) w s))))
1002 (else (values 'call #f e w s))))
1003 (values 'call #f e w s))))
1005 ;; s can't be valid source if we've unwrapped
1006 (syntax-type (syntax-object-expression e)
1008 (join-wraps w (syntax-object-wrap e))
1011 (syntax-type (annotation-expression e) r w (annotation-source e) rib))
1012 ((self-evaluating? e) (values 'constant #f e w s))
1013 (else (values 'other #f e w s)))))
1016 (lambda (e r w m esew)
1017 (define-syntax eval-if-c&e
1021 (if (eq? m 'c&e) (top-level-eval-hook x))
1024 (lambda () (syntax-type e r w no-source #f))
1025 (lambda (type value e w s)
1031 (chi-top-sequence (syntax (e1 e2 ...)) r w s m esew))))
1032 ((local-syntax-form)
1033 (chi-local-syntax value e r w s
1034 (lambda (body r w s)
1035 (chi-top-sequence body r w s m esew))))
1038 ((_ (x ...) e1 e2 ...)
1039 (let ((when-list (chi-when-list e (syntax (x ...)) w))
1040 (body (syntax (e1 e2 ...))))
1043 (if (memq 'eval when-list)
1044 (chi-top-sequence body r w s 'e '(eval))
1046 ((memq 'load when-list)
1047 (if (or (memq 'compile when-list)
1048 (and (eq? m 'c&e) (memq 'eval when-list)))
1049 (chi-top-sequence body r w s 'c&e '(compile load))
1050 (if (memq m '(c c&e))
1051 (chi-top-sequence body r w s 'c '(load))
1053 ((or (memq 'compile when-list)
1054 (and (eq? m 'c&e) (memq 'eval when-list)))
1055 (top-level-eval-hook
1056 (chi-top-sequence body r w s 'e '(eval)))
1058 (else (chi-void)))))))
1059 ((define-syntax-form)
1060 (let ((n (id-var-name value w)) (r (macros-only-env r)))
1063 (if (memq 'compile esew)
1064 (let ((e (chi-install-global n (chi e r w))))
1065 (top-level-eval-hook e)
1066 (if (memq 'load esew) e (chi-void)))
1067 (if (memq 'load esew)
1068 (chi-install-global n (chi e r w))
1071 (let ((e (chi-install-global n (chi e r w))))
1072 (top-level-eval-hook e)
1075 (if (memq 'eval esew)
1076 (top-level-eval-hook
1077 (chi-install-global n (chi e r w))))
1080 (let ((n (id-var-name value w)))
1081 (case (binding-type (lookup n r))
1084 (build-global-definition s n (chi e r w))))
1085 ((displaced-lexical)
1086 (syntax-error (wrap value w) "identifier out of context"))
1087 (else (syntax-error (wrap value w)
1088 "cannot define keyword at top level")))))
1089 (else (eval-if-c&e m (chi-expr type value e r w s))))))))
1094 (lambda () (syntax-type e r w no-source #f))
1095 (lambda (type value e w s)
1096 (chi-expr type value e r w s)))))
1099 (lambda (type value e r w s)
1102 (build-lexical-reference 'value s value))
1103 ((core) (value e r w s))
1106 (build-lexical-reference 'fun (source-annotation (car e)) value)
1110 (build-global-reference (source-annotation (car e)) value)
1112 ((constant) (build-data s (strip (source-wrap e w s) empty-wrap)))
1113 ((global) (build-global-reference s value))
1114 ((call) (chi-application (chi (car e) r w) e r w s))
1117 ((_ e1 e2 ...) (chi-sequence (syntax (e1 e2 ...)) r w s))))
1118 ((local-syntax-form)
1119 (chi-local-syntax value e r w s chi-sequence))
1122 ((_ (x ...) e1 e2 ...)
1123 (let ((when-list (chi-when-list e (syntax (x ...)) w)))
1124 (if (memq 'eval when-list)
1125 (chi-sequence (syntax (e1 e2 ...)) r w s)
1127 ((define-form define-syntax-form)
1128 (syntax-error (wrap value w) "invalid context for definition of"))
1130 (syntax-error (source-wrap e w s)
1131 "reference to pattern variable outside syntax form"))
1132 ((displaced-lexical)
1133 (syntax-error (source-wrap e w s)
1134 "reference to identifier outside its scope"))
1135 (else (syntax-error (source-wrap e w s))))))
1137 (define chi-application
1141 (build-application s x
1142 (map (lambda (e) (chi e r w)) (syntax (e1 ...))))))))
1145 (lambda (p e r w rib)
1146 (define rebuild-macro-output
1149 (cons (rebuild-macro-output (car x) m)
1150 (rebuild-macro-output (cdr x) m)))
1152 (let ((w (syntax-object-wrap x)))
1153 (let ((ms (wrap-marks w)) (s (wrap-subst w)))
1154 (make-syntax-object (syntax-object-expression x)
1155 (if (and (pair? ms) (eq? (car ms) the-anti-mark))
1157 (if rib (cons rib (cdr s)) (cdr s)))
1158 (make-wrap (cons m ms)
1160 (cons rib (cons 'shift s))
1161 (cons 'shift s))))))))
1163 (let* ((n (vector-length x)) (v (make-vector n)))
1164 (do ((i 0 (fx+ i 1)))
1167 (rebuild-macro-output (vector-ref x i) m)))))
1169 (syntax-error x "encountered raw symbol in macro output"))
1171 (rebuild-macro-output (p (wrap e (anti-mark w))) (new-mark))))
1174 ;; In processing the forms of the body, we create a new, empty wrap.
1175 ;; This wrap is augmented (destructively) each time we discover that
1176 ;; the next form is a definition. This is done:
1178 ;; (1) to allow the first nondefinition form to be a call to
1179 ;; one of the defined ids even if the id previously denoted a
1180 ;; definition keyword or keyword for a macro expanding into a
1182 ;; (2) to prevent subsequent definition forms (but unfortunately
1183 ;; not earlier ones) and the first nondefinition form from
1184 ;; confusing one of the bound identifiers for an auxiliary
1186 ;; (3) so that we do not need to restart the expansion of the
1187 ;; first nondefinition form, which is problematic anyway
1188 ;; since it might be the first element of a begin that we
1189 ;; have just spliced into the body (meaning if we restarted,
1190 ;; we'd really need to restart with the begin or the macro
1191 ;; call that expanded into the begin, and we'd have to give
1192 ;; up allowing (begin <defn>+ <expr>+), which is itself
1193 ;; problematic since we don't know if a begin contains only
1194 ;; definitions until we've expanded it).
1196 ;; Before processing the body, we also create a new environment
1197 ;; containing a placeholder for the bindings we will add later and
1198 ;; associate this environment with each form. In processing a
1199 ;; let-syntax or letrec-syntax, the associated environment may be
1200 ;; augmented with local keyword bindings, so the environment may
1201 ;; be different for different forms in the body. Once we have
1202 ;; gathered up all of the definitions, we evaluate the transformer
1203 ;; expressions and splice into r at the placeholder the new variable
1204 ;; and keyword bindings. This allows let-syntax or letrec-syntax
1205 ;; forms local to a portion or all of the body to shadow the
1206 ;; definition bindings.
1208 ;; Subforms of a begin, let-syntax, or letrec-syntax are spliced
1211 ;; outer-form is fully wrapped w/source
1212 (lambda (body outer-form r w)
1213 (let* ((r (cons '("placeholder" . (placeholder)) r))
1214 (ribcage (make-empty-ribcage))
1215 (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
1216 (let parse ((body (map (lambda (x) (cons r (wrap x w))) body))
1217 (ids '()) (labels '()) (vars '()) (vals '()) (bindings '()))
1219 (syntax-error outer-form "no expressions in body")
1220 (let ((e (cdar body)) (er (caar body)))
1222 (lambda () (syntax-type e er empty-wrap no-source ribcage))
1223 (lambda (type value e w s)
1226 (let ((id (wrap value w)) (label (gen-label)))
1227 (let ((var (gen-var id)))
1228 (extend-ribcage! ribcage id label)
1230 (cons id ids) (cons label labels)
1231 (cons var vars) (cons (cons er (wrap e w)) vals)
1232 (cons (make-binding 'lexical var) bindings)))))
1233 ((define-syntax-form)
1234 (let ((id (wrap value w)) (label (gen-label)))
1235 (extend-ribcage! ribcage id label)
1237 (cons id ids) (cons label labels)
1239 (cons (make-binding 'macro (cons er (wrap e w)))
1244 (parse (let f ((forms (syntax (e1 ...))))
1247 (cons (cons er (wrap (car forms) w))
1249 ids labels vars vals bindings))))
1250 ((local-syntax-form)
1251 (chi-local-syntax value e er w s
1252 (lambda (forms er w s)
1253 (parse (let f ((forms forms))
1256 (cons (cons er (wrap (car forms) w))
1258 ids labels vars vals bindings))))
1259 (else ; found a non-definition
1261 (build-sequence no-source
1263 (chi (cdr x) (car x) empty-wrap))
1264 (cons (cons er (source-wrap e w s))
1267 (if (not (valid-bound-ids? ids))
1268 (syntax-error outer-form
1269 "invalid or duplicate identifier in definition"))
1270 (let loop ((bs bindings) (er-cache #f) (r-cache #f))
1271 (if (not (null? bs))
1272 (let* ((b (car bs)))
1273 (if (eq? (car b) 'macro)
1274 (let* ((er (cadr b))
1276 (if (eq? er er-cache)
1278 (macros-only-env er))))
1280 (eval-local-transformer
1281 (chi (cddr b) r-cache empty-wrap)))
1282 (loop (cdr bs) er r-cache))
1283 (loop (cdr bs) er-cache r-cache)))))
1284 (set-cdr! r (extend-env labels bindings (cdr r)))
1285 (build-letrec no-source
1288 (chi (cdr x) (car x) empty-wrap))
1290 (build-sequence no-source
1292 (chi (cdr x) (car x) empty-wrap))
1293 (cons (cons er (source-wrap e w s))
1294 (cdr body)))))))))))))))))
1296 (define chi-lambda-clause
1299 (((id ...) e1 e2 ...)
1300 (let ((ids (syntax (id ...))))
1301 (if (not (valid-bound-ids? ids))
1302 (syntax-error e "invalid parameter list in")
1303 (let ((labels (gen-labels ids))
1304 (new-vars (map gen-var ids)))
1306 (chi-body (syntax (e1 e2 ...))
1308 (extend-var-env labels new-vars r)
1309 (make-binding-wrap ids labels w)))))))
1311 (let ((old-ids (lambda-var-list (syntax ids))))
1312 (if (not (valid-bound-ids? old-ids))
1313 (syntax-error e "invalid parameter list in")
1314 (let ((labels (gen-labels old-ids))
1315 (new-vars (map gen-var old-ids)))
1316 (k (let f ((ls1 (cdr new-vars)) (ls2 (car new-vars)))
1319 (f (cdr ls1) (cons (car ls1) ls2))))
1320 (chi-body (syntax (e1 e2 ...))
1322 (extend-var-env labels new-vars r)
1323 (make-binding-wrap old-ids labels w)))))))
1324 (_ (syntax-error e)))))
1326 (define chi-local-syntax
1327 (lambda (rec? e r w s k)
1329 ((_ ((id val) ...) e1 e2 ...)
1330 (let ((ids (syntax (id ...))))
1331 (if (not (valid-bound-ids? ids))
1332 (syntax-error e "duplicate bound keyword in")
1333 (let ((labels (gen-labels ids)))
1334 (let ((new-w (make-binding-wrap ids labels w)))
1335 (k (syntax (e1 e2 ...))
1338 (let ((w (if rec? new-w w))
1339 (trans-r (macros-only-env r)))
1341 (make-binding 'macro
1342 (eval-local-transformer (chi x trans-r w))))
1343 (syntax (val ...))))
1347 (_ (syntax-error (source-wrap e w s))))))
1349 (define eval-local-transformer
1351 (let ((p (local-eval-hook expanded)))
1354 (syntax-error p "nonprocedure transfomer")))))
1358 (build-application no-source (build-primref no-source 'void) '())))
1362 (and (nonsymbol-id? x)
1363 (free-id=? x (syntax (... ...))))))
1367 ;;; strips all annotations from potentially circular reader output
1369 (define strip-annotation
1373 (let ((new (cons #f #f)))
1374 (when parent (set-annotation-stripped! parent new))
1375 (set-car! new (strip-annotation (car x) #f))
1376 (set-cdr! new (strip-annotation (cdr x) #f))
1379 (or (annotation-stripped x)
1380 (strip-annotation (annotation-expression x) x)))
1382 (let ((new (make-vector (vector-length x))))
1383 (when parent (set-annotation-stripped! parent new))
1384 (let loop ((i (- (vector-length x) 1)))
1386 (vector-set! new i (strip-annotation (vector-ref x i) #f))
1391 ;;; strips syntax-objects down to top-wrap; if top-wrap is layered directly
1392 ;;; on an annotation, strips the annotation as well.
1393 ;;; since only the head of a list is annotated by the reader, not each pair
1394 ;;; in the spine, we also check for pairs whose cars are annotated in case
1395 ;;; we've been passed the cdr of an annotated list
1400 (if (or (annotation? x) (and (pair? x) (annotation? (car x))))
1401 (strip-annotation x #f)
1406 (strip (syntax-object-expression x) (syntax-object-wrap x)))
1408 (let ((a (f (car x))) (d (f (cdr x))))
1409 (if (and (eq? a (car x)) (eq? d (cdr x)))
1413 (let ((old (vector->list x)))
1414 (let ((new (map f old)))
1415 (if (andmap eq? old new) x (list->vector new)))))
1418 ;;; lexical variables
1422 (let ((id (if (syntax-object? id) (syntax-object-expression id) id)))
1423 (if (annotation? id)
1424 (build-lexical-var (annotation-source id) (annotation-expression id))
1425 (build-lexical-var no-source id)))))
1427 (define lambda-var-list
1429 (let lvl ((vars vars) (ls '()) (w empty-wrap))
1431 ((pair? vars) (lvl (cdr vars) (cons (wrap (car vars) w) ls) w))
1432 ((id? vars) (cons (wrap vars w) ls))
1434 ((syntax-object? vars)
1435 (lvl (syntax-object-expression vars)
1437 (join-wraps w (syntax-object-wrap vars))))
1439 (lvl (annotation-expression vars) ls w))
1440 ; include anything else to be caught by subsequent error
1442 (else (cons vars ls))))))
1444 ;;; core transformers
1446 (global-extend 'local-syntax 'letrec-syntax #t)
1447 (global-extend 'local-syntax 'let-syntax #f)
1449 (global-extend 'core 'fluid-let-syntax
1452 ((_ ((var val) ...) e1 e2 ...)
1453 (valid-bound-ids? (syntax (var ...)))
1454 (let ((names (map (lambda (x) (id-var-name x w)) (syntax (var ...)))))
1457 (case (binding-type (lookup n r))
1458 ((displaced-lexical)
1459 (syntax-error (source-wrap id w s)
1460 "identifier out of context"))))
1464 (syntax (e1 e2 ...))
1468 (let ((trans-r (macros-only-env r)))
1470 (make-binding 'macro
1471 (eval-local-transformer (chi x trans-r w))))
1472 (syntax (val ...))))
1475 (_ (syntax-error (source-wrap e w s))))))
1477 (global-extend 'core 'quote
1480 ((_ e) (build-data s (strip (syntax e) w)))
1481 (_ (syntax-error (source-wrap e w s))))))
1483 (global-extend 'core 'syntax
1486 (lambda (src e r maps ellipsis?)
1488 (let ((label (id-var-name e empty-wrap)))
1489 (let ((b (lookup label r)))
1490 (if (eq? (binding-type b) 'syntax)
1493 (let ((var.lev (binding-value b)))
1494 (gen-ref src (car var.lev) (cdr var.lev) maps)))
1495 (lambda (var maps) (values `(ref ,var) maps)))
1497 (syntax-error src "misplaced ellipsis in syntax form")
1498 (values `(quote ,e) maps)))))
1501 (ellipsis? (syntax dots))
1502 (gen-syntax src (syntax e) r maps (lambda (x) #f)))
1504 ; this could be about a dozen lines of code, except that we
1505 ; choose to handle (syntax (x ... ...)) forms
1506 (ellipsis? (syntax dots))
1507 (let f ((y (syntax y))
1511 (gen-syntax src (syntax x) r
1512 (cons '() maps) ellipsis?))
1514 (if (null? (car maps))
1516 "extra ellipsis in syntax form")
1517 (values (gen-map x (car maps))
1521 (ellipsis? (syntax dots))
1525 (lambda () (k (cons '() maps)))
1527 (if (null? (car maps))
1529 "extra ellipsis in syntax form")
1530 (values (gen-mappend x (car maps))
1532 (_ (call-with-values
1533 (lambda () (gen-syntax src y r maps ellipsis?))
1536 (lambda () (k maps))
1538 (values (gen-append x y) maps)))))))))
1541 (lambda () (gen-syntax src (syntax x) r maps ellipsis?))
1544 (lambda () (gen-syntax src (syntax y) r maps ellipsis?))
1545 (lambda (y maps) (values (gen-cons x y) maps))))))
1549 (gen-syntax src (syntax (e1 e2 ...)) r maps ellipsis?))
1550 (lambda (e maps) (values (gen-vector e) maps))))
1551 (_ (values `(quote ,e) maps))))))
1554 (lambda (src var level maps)
1558 (syntax-error src "missing ellipsis in syntax form")
1560 (lambda () (gen-ref src var (fx- level 1) (cdr maps)))
1561 (lambda (outer-var outer-maps)
1562 (let ((b (assq outer-var (car maps))))
1564 (values (cdr b) maps)
1565 (let ((inner-var (gen-var 'tmp)))
1567 (cons (cons (cons outer-var inner-var)
1569 outer-maps)))))))))))
1573 `(apply (primitive append) ,(gen-map e map-env))))
1577 (let ((formals (map cdr map-env))
1578 (actuals (map (lambda (x) `(ref ,(car x))) map-env)))
1581 ; identity map equivalence:
1582 ; (map (lambda (x) x) y) == y
1585 (lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
1587 ; eta map equivalence:
1588 ; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
1589 `(map (primitive ,(car e))
1590 ,@(map (let ((r (map cons formals actuals)))
1591 (lambda (x) (cdr (assq (cadr x) r))))
1593 (else `(map (lambda ,formals ,e) ,@actuals))))))
1599 (if (eq? (car x) 'quote)
1600 `(quote (,(cadr x) . ,(cadr y)))
1601 (if (eq? (cadr y) '())
1604 ((list) `(list ,x ,@(cdr y)))
1605 (else `(cons ,x ,y)))))
1609 (if (equal? y '(quote ()))
1616 ((eq? (car x) 'list) `(vector ,@(cdr x)))
1617 ((eq? (car x) 'quote) `(quote #(,@(cadr x))))
1618 (else `(list->vector ,x)))))
1624 ((ref) (build-lexical-reference 'value no-source (cadr x)))
1625 ((primitive) (build-primref no-source (cadr x)))
1626 ((quote) (build-data no-source (cadr x)))
1627 ((lambda) (build-lambda no-source (cadr x) (regen (caddr x))))
1628 ((map) (let ((ls (map regen (cdr x))))
1629 (build-application no-source
1630 (if (fx= (length ls) 2)
1631 (build-primref no-source 'map)
1632 ; really need to do our own checking here
1633 (build-primref no-source 2 'map)) ; require error check
1635 (else (build-application no-source
1636 (build-primref no-source (car x))
1637 (map regen (cdr x)))))))
1640 (let ((e (source-wrap e w s)))
1644 (lambda () (gen-syntax e (syntax x) r '() ellipsis?))
1645 (lambda (e maps) (regen e))))
1646 (_ (syntax-error e)))))))
1649 (global-extend 'core 'lambda
1653 (chi-lambda-clause (source-wrap e w s) (syntax c) r w
1654 (lambda (vars body) (build-lambda s vars body)))))))
1657 (global-extend 'core 'let
1659 (define (chi-let e r w s constructor ids vals exps)
1660 (if (not (valid-bound-ids? ids))
1661 (syntax-error e "duplicate bound variable in")
1662 (let ((labels (gen-labels ids))
1663 (new-vars (map gen-var ids)))
1664 (let ((nw (make-binding-wrap ids labels w))
1665 (nr (extend-var-env labels new-vars r)))
1668 (map (lambda (x) (chi x r w)) vals)
1669 (chi-body exps (source-wrap e nw s) nr nw))))))
1672 ((_ ((id val) ...) e1 e2 ...)
1677 (syntax (e1 e2 ...))))
1678 ((_ f ((id val) ...) e1 e2 ...)
1684 (syntax (e1 e2 ...))))
1685 (_ (syntax-error (source-wrap e w s)))))))
1688 (global-extend 'core 'letrec
1691 ((_ ((id val) ...) e1 e2 ...)
1692 (let ((ids (syntax (id ...))))
1693 (if (not (valid-bound-ids? ids))
1694 (syntax-error e "duplicate bound variable in")
1695 (let ((labels (gen-labels ids))
1696 (new-vars (map gen-var ids)))
1697 (let ((w (make-binding-wrap ids labels w))
1698 (r (extend-var-env labels new-vars r)))
1701 (map (lambda (x) (chi x r w)) (syntax (val ...)))
1702 (chi-body (syntax (e1 e2 ...)) (source-wrap e w s) r w)))))))
1703 (_ (syntax-error (source-wrap e w s))))))
1706 (global-extend 'core 'set!
1711 (let ((val (chi (syntax val) r w))
1712 (n (id-var-name (syntax id) w)))
1713 (let ((b (lookup n r)))
1714 (case (binding-type b)
1716 (build-lexical-assignment s (binding-value b) val))
1717 ((global) (build-global-assignment s n val))
1718 ((displaced-lexical)
1719 (syntax-error (wrap (syntax id) w)
1720 "identifier out of context"))
1721 (else (syntax-error (source-wrap e w s)))))))
1722 ((_ (getter arg ...) val)
1723 (build-application s
1724 (chi (syntax (setter getter)) r w)
1725 (map (lambda (e) (chi e r w))
1726 (syntax (arg ... val)))))
1727 (_ (syntax-error (source-wrap e w s))))))
1729 (global-extend 'begin 'begin '())
1731 (global-extend 'define 'define '())
1733 (global-extend 'define-syntax 'define-syntax '())
1735 (global-extend 'eval-when 'eval-when '())
1737 (global-extend 'core 'syntax-case
1739 (define convert-pattern
1740 ; accepts pattern & keys
1741 ; returns syntax-dispatch pattern & ids
1742 (lambda (pattern keys)
1743 (let cvt ((p pattern) (n 0) (ids '()))
1745 (if (bound-id-member? p keys)
1746 (values (vector 'free-id p) ids)
1747 (values 'any (cons (cons p n) ids)))
1750 (ellipsis? (syntax dots))
1752 (lambda () (cvt (syntax x) (fx+ n 1) ids))
1754 (values (if (eq? p 'any) 'each-any (vector 'each p))
1758 (lambda () (cvt (syntax y) n ids))
1761 (lambda () (cvt (syntax x) n ids))
1763 (values (cons x y) ids))))))
1764 (() (values '() ids))
1767 (lambda () (cvt (syntax (x ...)) n ids))
1768 (lambda (p ids) (values (vector 'vector p) ids))))
1769 (x (values (vector 'atom (strip p empty-wrap)) ids)))))))
1771 (define build-dispatch-call
1772 (lambda (pvars exp y r)
1773 (let ((ids (map car pvars)) (levels (map cdr pvars)))
1774 (let ((labels (gen-labels ids)) (new-vars (map gen-var ids)))
1775 (build-application no-source
1776 (build-primref no-source 'apply)
1777 (list (build-lambda no-source new-vars
1781 (map (lambda (var level)
1782 (make-binding 'syntax `(,var . ,level)))
1786 (make-binding-wrap ids labels empty-wrap)))
1790 (lambda (x keys clauses r pat fender exp)
1792 (lambda () (convert-pattern pat keys))
1795 ((not (distinct-bound-ids? (map car pvars)))
1797 "duplicate pattern variable in syntax-case pattern"))
1798 ((not (andmap (lambda (x) (not (ellipsis? (car x)))) pvars))
1800 "misplaced ellipsis in syntax-case pattern"))
1802 (let ((y (gen-var 'tmp)))
1803 ; fat finger binding and references to temp variable y
1804 (build-application no-source
1805 (build-lambda no-source (list y)
1806 (let ((y (build-lexical-reference 'value no-source y)))
1807 (build-conditional no-source
1808 (syntax-case fender ()
1810 (_ (build-conditional no-source
1812 (build-dispatch-call pvars fender y r)
1813 (build-data no-source #f))))
1814 (build-dispatch-call pvars exp y r)
1815 (gen-syntax-case x keys clauses r))))
1816 (list (if (eq? p 'any)
1817 (build-application no-source
1818 (build-primref no-source 'list)
1820 (build-application no-source
1821 (build-primref no-source 'syntax-dispatch)
1822 (list x (build-data no-source p)))))))))))))
1824 (define gen-syntax-case
1825 (lambda (x keys clauses r)
1827 (build-application no-source
1828 (build-primref no-source 'syntax-error)
1830 (syntax-case (car clauses) ()
1832 (if (and (id? (syntax pat))
1833 (andmap (lambda (x) (not (free-id=? (syntax pat) x)))
1834 (cons (syntax (... ...)) keys)))
1835 (let ((labels (list (gen-label)))
1836 (var (gen-var (syntax pat))))
1837 (build-application no-source
1838 (build-lambda no-source (list var)
1841 (list (make-binding 'syntax `(,var . 0)))
1843 (make-binding-wrap (syntax (pat))
1844 labels empty-wrap)))
1846 (gen-clause x keys (cdr clauses) r
1847 (syntax pat) #t (syntax exp))))
1849 (gen-clause x keys (cdr clauses) r
1850 (syntax pat) (syntax fender) (syntax exp)))
1851 (_ (syntax-error (car clauses) "invalid syntax-case clause"))))))
1854 (let ((e (source-wrap e w s)))
1856 ((_ val (key ...) m ...)
1857 (if (andmap (lambda (x) (and (id? x) (not (ellipsis? x))))
1859 (let ((x (gen-var 'tmp)))
1860 ; fat finger binding and references to temp variable x
1861 (build-application s
1862 (build-lambda no-source (list x)
1863 (gen-syntax-case (build-lexical-reference 'value no-source x)
1864 (syntax (key ...)) (syntax (m ...))
1866 (list (chi (syntax val) r empty-wrap))))
1867 (syntax-error e "invalid literals list in"))))))))
1869 ;;; The portable sc-expand seeds chi-top's mode m with 'e (for
1870 ;;; evaluating) and esew (which stands for "eval syntax expanders
1871 ;;; when") with '(eval). In Chez Scheme, m is set to 'c instead of e
1872 ;;; if we are compiling a file, and esew is set to
1873 ;;; (eval-syntactic-expanders-when), which defaults to the list
1874 ;;; '(compile load eval). This means that, by default, top-level
1875 ;;; syntactic definitions are evaluated immediately after they are
1876 ;;; expanded, and the expanded definitions are also residualized into
1877 ;;; the object file if we are compiling a file.
1879 (let ((m 'e) (esew '(eval)))
1881 (if (and (pair? x) (equal? (car x) noexpand))
1883 (chi-top x null-env top-wrap m esew)))))
1886 (let ((m 'e) (esew '(eval)))
1888 (if (and (pair? x) (equal? (car x) noexpand))
1893 (if (null? rest) m (car rest))
1894 (if (or (null? rest) (null? (cdr rest)))
1902 (set! datum->syntax-object
1904 (arg-check nonsymbol-id? id 'datum->syntax-object)
1905 (make-syntax-object datum (syntax-object-wrap id))))
1907 (set! syntax-object->datum
1908 ; accepts any object, since syntax objects may consist partially
1909 ; or entirely of unwrapped, nonsymbolic data
1911 (strip x empty-wrap)))
1913 (set! generate-temporaries
1915 (arg-check list? ls 'generate-temporaries)
1916 (map (lambda (x) (wrap (gensym-hook) top-wrap)) ls)))
1918 (set! free-identifier=?
1920 (arg-check nonsymbol-id? x 'free-identifier=?)
1921 (arg-check nonsymbol-id? y 'free-identifier=?)
1924 (set! bound-identifier=?
1926 (arg-check nonsymbol-id? x 'bound-identifier=?)
1927 (arg-check nonsymbol-id? y 'bound-identifier=?)
1931 (lambda (object . messages)
1932 (for-each (lambda (x) (arg-check string? x 'syntax-error)) messages)
1933 (let ((message (if (null? messages)
1935 (apply string-append messages))))
1936 (error-hook #f message (strip object empty-wrap)))))
1938 (set! install-global-transformer
1940 (arg-check symbol? sym 'define-syntax)
1941 (arg-check procedure? v 'define-syntax)
1942 (global-extend 'macro sym v)))
1944 ;;; syntax-dispatch expects an expression and a pattern. If the expression
1945 ;;; matches the pattern a list of the matching expressions for each
1946 ;;; "any" is returned. Otherwise, #f is returned. (This use of #f will
1947 ;;; not work on r4rs implementations that violate the ieee requirement
1948 ;;; that #f and () be distinct.)
1950 ;;; The expression is matched with the pattern as follows:
1952 ;;; pattern: matches:
1955 ;;; (<pattern>1 . <pattern>2) (<pattern>1 . <pattern>2)
1957 ;;; #(free-id <key>) <key> with free-identifier=?
1958 ;;; #(each <pattern>) (<pattern>*)
1959 ;;; #(vector <pattern>) (list->vector <pattern>)
1960 ;;; #(atom <object>) <object> with "equal?"
1962 ;;; Vector cops out to pair under assumption that vectors are rare. If
1963 ;;; not, should convert to:
1964 ;;; #(vector <pattern>*) #(<pattern>*)
1972 (match-each (annotation-expression e) p w))
1974 (let ((first (match (car e) p w '())))
1976 (let ((rest (match-each (cdr e) p w)))
1977 (and rest (cons first rest))))))
1980 (match-each (syntax-object-expression e)
1982 (join-wraps w (syntax-object-wrap e))))
1985 (define match-each-any
1989 (match-each-any (annotation-expression e) w))
1991 (let ((l (match-each-any (cdr e) w)))
1992 (and l (cons (wrap (car e) w) l))))
1995 (match-each-any (syntax-object-expression e)
1996 (join-wraps w (syntax-object-wrap e))))
2003 ((eq? p 'any) (cons '() r))
2004 ((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
2005 ((eq? p 'each-any) (cons '() r))
2007 (case (vector-ref p 0)
2008 ((each) (match-empty (vector-ref p 1) r))
2010 ((vector) (match-empty (vector-ref p 1) r)))))))
2015 ((null? p) (and (null? e) r))
2017 (and (pair? e) (match (car e) (car p) w
2018 (match (cdr e) (cdr p) w r))))
2020 (let ((l (match-each-any e w))) (and l (cons l r))))
2022 (case (vector-ref p 0)
2025 (match-empty (vector-ref p 1) r)
2026 (let ((l (match-each e (vector-ref p 1) w)))
2028 (let collect ((l l))
2031 (cons (map car l) (collect (map cdr l)))))))))
2032 ((free-id) (and (id? e) (free-id=? (wrap e w) (vector-ref p 1)) r))
2033 ((atom) (and (equal? (vector-ref p 1) (strip e w)) r))
2036 (match (vector->list e) (vector-ref p 1) w r))))))))
2042 ((eq? p 'any) (cons (wrap e w) r))
2045 (unannotate (syntax-object-expression e))
2047 (join-wraps w (syntax-object-wrap e))
2049 (else (match* (unannotate e) p w r)))))
2051 (set! syntax-dispatch
2054 ((eq? p 'any) (list e))
2056 (match* (unannotate (syntax-object-expression e))
2057 p (syntax-object-wrap e) '()))
2058 (else (match* (unannotate e) p empty-wrap '())))))
2062 (define-syntax with-syntax
2066 (syntax (begin e1 e2 ...)))
2067 ((_ ((out in)) e1 e2 ...)
2068 (syntax (syntax-case in () (out (begin e1 e2 ...)))))
2069 ((_ ((out in) ...) e1 e2 ...)
2070 (syntax (syntax-case (list in ...) ()
2071 ((out ...) (begin e1 e2 ...))))))))
2073 (define-syntax syntax-rules
2076 ((_ (k ...) ((keyword . pattern) template) ...)
2078 (syntax-case x (k ...)
2079 ((dummy . pattern) (syntax template))
2085 ((let* ((x v) ...) e1 e2 ...)
2086 (andmap identifier? (syntax (x ...)))
2087 (let f ((bindings (syntax ((x v) ...))))
2088 (if (null? bindings)
2089 (syntax (let () e1 e2 ...))
2090 (with-syntax ((body (f (cdr bindings)))
2091 (binding (car bindings)))
2092 (syntax (let (binding) body)))))))))
2096 (syntax-case orig-x ()
2097 ((_ ((var init . step) ...) (e0 e1 ...) c ...)
2098 (with-syntax (((step ...)
2103 (_ (syntax-error orig-x))))
2105 (syntax (step ...)))))
2106 (syntax-case (syntax (e1 ...)) ()
2107 (() (syntax (let doloop ((var init) ...)
2109 (begin c ... (doloop step ...))))))
2111 (syntax (let doloop ((var init) ...)
2114 (begin c ... (doloop step ...))))))))))))
2116 (define-syntax quasiquote
2120 (with-syntax ((x x) (y y))
2121 (syntax-case (syntax y) (quote list)
2123 (syntax-case (syntax x) (quote)
2124 ((quote dx) (syntax (quote (dx . dy))))
2125 (_ (if (null? (syntax dy))
2127 (syntax (cons x y))))))
2128 ((list . stuff) (syntax (list x . stuff)))
2129 (else (syntax (cons x y)))))))
2132 (with-syntax ((x x) (y y))
2133 (syntax-case (syntax y) (quote)
2134 ((quote ()) (syntax x))
2135 (_ (syntax (append x y)))))))
2138 (with-syntax ((x x))
2139 (syntax-case (syntax x) (quote list)
2140 ((quote (x ...)) (syntax (quote #(x ...))))
2141 ((list x ...) (syntax (vector x ...)))
2142 (_ (syntax (list->vector x)))))))
2145 (syntax-case p (unquote unquote-splicing quasiquote)
2149 (quasicons (syntax (quote unquote))
2150 (quasi (syntax (p)) (- lev 1)))))
2151 (((unquote-splicing p) . q)
2153 (quasiappend (syntax p) (quasi (syntax q) lev))
2154 (quasicons (quasicons (syntax (quote unquote-splicing))
2155 (quasi (syntax (p)) (- lev 1)))
2156 (quasi (syntax q) lev))))
2158 (quasicons (syntax (quote quasiquote))
2159 (quasi (syntax (p)) (+ lev 1))))
2161 (quasicons (quasi (syntax p) lev) (quasi (syntax q) lev)))
2162 (#(x ...) (quasivector (quasi (syntax (x ...)) lev)))
2163 (p (syntax (quote p)))))))
2166 ((_ e) (quasi (syntax e) 0))))))
2168 (define-syntax include
2172 (let ((p (open-input-file fn)))
2173 (let f ((x (read p)))
2175 (begin (close-input-port p) '())
2176 (cons (datum->syntax-object k x)
2180 (let ((fn (syntax-object->datum (syntax filename))))
2181 (with-syntax (((exp ...) (read-file fn (syntax k))))
2182 (syntax (begin exp ...))))))))
2184 (define-syntax unquote
2189 "expression ,~s not valid outside of quasiquote"
2190 (syntax-object->datum (syntax e)))))))
2192 (define-syntax unquote-splicing
2196 (error 'unquote-splicing
2197 "expression ,@~s not valid outside of quasiquote"
2198 (syntax-object->datum (syntax e)))))))
2205 ((body (let f ((clause (syntax m1)) (clauses (syntax (m2 ...))))
2207 (syntax-case clause (else)
2208 ((else e1 e2 ...) (syntax (begin e1 e2 ...)))
2209 (((k ...) e1 e2 ...)
2210 (syntax (if (memv t '(k ...)) (begin e1 e2 ...))))
2211 (_ (syntax-error x)))
2212 (with-syntax ((rest (f (car clauses) (cdr clauses))))
2213 (syntax-case clause (else)
2214 (((k ...) e1 e2 ...)
2215 (syntax (if (memv t '(k ...))
2218 (_ (syntax-error x))))))))
2219 (syntax (let ((t e)) body)))))))
2221 (define-syntax identifier-syntax
2229 (identifier? (syntax id))
2232 (syntax (e x (... ...)))))))))))