distcheck fixen
[bpt/guile.git] / module / ice-9 / psyntax.scm
CommitLineData
677cd590
RB
1;;;; -*-scheme-*-
2;;;;
cd5fea8d 3;;;; Copyright (C) 2001, 2003, 2006 Free Software Foundation, Inc.
86b96c16 4;;;;
73be1d9e
MV
5;;;; This library is free software; you can redistribute it and/or
6;;;; modify it under the terms of the GNU Lesser General Public
7;;;; License as published by the Free Software Foundation; either
8;;;; version 2.1 of the License, or (at your option) any later version.
86b96c16 9;;;;
73be1d9e 10;;;; This library is distributed in the hope that it will be useful,
86b96c16 11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;;; Lesser General Public License for more details.
86b96c16 14;;;;
73be1d9e
MV
15;;;; You should have received a copy of the GNU Lesser General Public
16;;;; License along with this library; if not, write to the Free Software
92205699 17;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
86b96c16
MD
18;;;;
19\f
20
a63812a2
JB
21;;; Portable implementation of syntax-case
22;;; Extracted from Chez Scheme Version 5.9f
23;;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman
24
86b96c16
MD
25;;; Modified by Mikael Djurfeldt <djurfeldt@nada.kth.se> according
26;;; to the ChangeLog distributed in the same directory as this file:
27;;; 1997-08-19, 1997-09-03, 1997-09-10, 2000-08-13, 2000-08-24,
28;;; 2000-09-12, 2001-03-08
29
a63812a2
JB
30;;; Copyright (c) 1992-1997 Cadence Research Systems
31;;; Permission to copy this software, in whole or in part, to use this
32;;; software for any lawful purpose, and to redistribute this software
33;;; is granted subject to the restriction that all copies made of this
34;;; software must include this copyright notice in full. This software
35;;; is provided AS IS, with NO WARRANTY, EITHER EXPRESS OR IMPLIED,
36;;; INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
37;;; OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE
38;;; AUTHORS BE LIABLE FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES OF ANY
39;;; NATURE WHATSOEVER.
40
a63812a2
JB
41;;; Before attempting to port this code to a new implementation of
42;;; Scheme, please read the notes below carefully.
43
44
45;;; This file defines the syntax-case expander, sc-expand, and a set
46;;; of associated syntactic forms and procedures. Of these, the
47;;; following are documented in The Scheme Programming Language,
48;;; Second Edition (R. Kent Dybvig, Prentice Hall, 1996). Most are
49;;; also documented in the R4RS and draft R5RS.
50;;;
51;;; bound-identifier=?
52;;; datum->syntax-object
53;;; define-syntax
54;;; fluid-let-syntax
55;;; free-identifier=?
56;;; generate-temporaries
57;;; identifier?
58;;; identifier-syntax
59;;; let-syntax
60;;; letrec-syntax
61;;; syntax
62;;; syntax-case
63;;; syntax-object->datum
64;;; syntax-rules
65;;; with-syntax
66;;;
67;;; All standard Scheme syntactic forms are supported by the expander
68;;; or syntactic abstractions defined in this file. Only the R4RS
69;;; delay is omitted, since its expansion is implementation-dependent.
70
71;;; The remaining exports are listed below:
72;;;
73;;; (sc-expand datum)
74;;; if datum represents a valid expression, sc-expand 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-error object message)
83;;; used to report errors found during expansion
84;;; (install-global-transformer symbol value)
85;;; used by expanded code to install top-level syntactic abstractions
86;;; (syntax-dispatch e p)
87;;; used by expanded code to handle syntax-case matching
88
89;;; The following nonstandard procedures must be provided by the
90;;; implementation for this code to run.
91;;;
92;;; (void)
93;;; returns the implementation's cannonical "unspecified value". This
94;;; usually works: (define void (lambda () (if #f #f))).
95;;;
96;;; (andmap proc list1 list2 ...)
97;;; returns true if proc returns true when applied to each element of list1
98;;; along with the corresponding elements of list2 ....
99;;; The following definition works but does no error checking:
100;;;
101;;; (define andmap
102;;; (lambda (f first . rest)
103;;; (or (null? first)
104;;; (if (null? rest)
105;;; (let andmap ((first first))
106;;; (let ((x (car first)) (first (cdr first)))
107;;; (if (null? first)
108;;; (f x)
109;;; (and (f x) (andmap first)))))
110;;; (let andmap ((first first) (rest rest))
111;;; (let ((x (car first))
112;;; (xr (map car rest))
113;;; (first (cdr first))
114;;; (rest (map cdr rest)))
115;;; (if (null? first)
116;;; (apply f (cons x xr))
117;;; (and (apply f (cons x xr)) (andmap first rest)))))))))
118;;;
119;;; The following nonstandard procedures must also be provided by the
120;;; implementation for this code to run using the standard portable
121;;; hooks and output constructors. They are not used by expanded code,
122;;; and so need be present only at expansion time.
123;;;
124;;; (eval x)
125;;; where x is always in the form ("noexpand" expr).
126;;; returns the value of expr. the "noexpand" flag is used to tell the
127;;; evaluator/expander that no expansion is necessary, since expr has
128;;; already been fully expanded to core forms.
129;;;
130;;; eval will not be invoked during the loading of psyntax.pp. After
131;;; psyntax.pp has been loaded, the expansion of any macro definition,
132;;; whether local or global, will result in a call to eval. If, however,
133;;; sc-expand has already been registered as the expander to be used
134;;; by eval, and eval accepts one argument, nothing special must be done
135;;; to support the "noexpand" flag, since it is handled by sc-expand.
136;;;
137;;; (error who format-string why what)
138;;; where who is either a symbol or #f, format-string is always "~a ~s",
139;;; why is always a string, and what may be any object. error should
140;;; signal an error with a message something like
141;;;
142;;; "error in <who>: <why> <what>"
143;;;
144;;; (gensym)
145;;; returns a unique symbol each time it's called
146;;;
147;;; (putprop symbol key value)
148;;; (getprop symbol key)
149;;; key is always the symbol *sc-expander*; value may be any object.
150;;; putprop should associate the given value with the given symbol in
151;;; some way that it can be retrieved later with getprop.
152
153;;; When porting to a new Scheme implementation, you should define the
154;;; procedures listed above, load the expanded version of psyntax.ss
155;;; (psyntax.pp, which should be available whereever you found
156;;; psyntax.ss), and register sc-expand as the current expander (how
157;;; you do this depends upon your implementation of Scheme). You may
158;;; change the hooks and constructors defined toward the beginning of
159;;; the code below, but to avoid bootstrapping problems, do so only
160;;; after you have a working version of the expander.
161
162;;; Chez Scheme allows the syntactic form (syntax <template>) to be
163;;; abbreviated to #'<template>, just as (quote <datum>) may be
164;;; abbreviated to '<datum>. The #' syntax makes programs written
165;;; using syntax-case shorter and more readable and draws out the
166;;; intuitive connection between syntax and quote.
167
168;;; If you find that this code loads or runs slowly, consider
169;;; switching to faster hardware or a faster implementation of
170;;; Scheme. In Chez Scheme on a 200Mhz Pentium Pro, expanding,
171;;; compiling (with full optimization), and loading this file takes
172;;; between one and two seconds.
173
174;;; In the expander implementation, we sometimes use syntactic abstractions
175;;; when procedural abstractions would suffice. For example, we define
176;;; top-wrap and top-marked? as
177;;; (define-syntax top-wrap (identifier-syntax '((top))))
178;;; (define-syntax top-marked?
179;;; (syntax-rules ()
180;;; ((_ w) (memq 'top (wrap-marks w)))))
181;;; rather than
182;;; (define top-wrap '((top)))
183;;; (define top-marked?
184;;; (lambda (w) (memq 'top (wrap-marks w))))
185;;; On ther other hand, we don't do this consistently; we define make-wrap,
186;;; wrap-marks, and wrap-subst simply as
187;;; (define make-wrap cons)
188;;; (define wrap-marks car)
189;;; (define wrap-subst cdr)
190;;; In Chez Scheme, the syntactic and procedural forms of these
191;;; abstractions are equivalent, since the optimizer consistently
192;;; integrates constants and small procedures. Some Scheme
193;;; implementations, however, may benefit from more consistent use
194;;; of one form or the other.
195
196
197;;; implementation information:
198
199;;; "begin" is treated as a splicing construct at top level and at
200;;; the beginning of bodies. Any sequence of expressions that would
201;;; be allowed where the "begin" occurs is allowed.
202
203;;; "let-syntax" and "letrec-syntax" are also treated as splicing
204;;; constructs, in violation of the R4RS appendix and probably the R5RS
205;;; when it comes out. A consequence, let-syntax and letrec-syntax do
206;;; not create local contours, as do let and letrec. Although the
207;;; functionality is greater as it is presently implemented, we will
208;;; probably change it to conform to the R4RS/expected R5RS.
209
210;;; Objects with no standard print syntax, including objects containing
211;;; cycles and syntax object, are allowed in quoted data as long as they
212;;; are contained within a syntax form or produced by datum->syntax-object.
213;;; Such objects are never copied.
214
215;;; All identifiers that don't have macro definitions and are not bound
216;;; lexically are assumed to be global variables
217
218;;; Top-level definitions of macro-introduced identifiers are allowed.
219;;; This may not be appropriate for implementations in which the
220;;; model is that bindings are created by definitions, as opposed to
221;;; one in which initial values are assigned by definitions.
222
223;;; Top-level variable definitions of syntax keywords is not permitted.
224;;; Any solution allowing this would be kludgey and would yield
225;;; surprising results in some cases. We can provide an undefine-syntax
226;;; form. The questions is, should define be an implicit undefine-syntax?
227;;; We've decided no for now.
228
229;;; Identifiers and syntax objects are implemented as vectors for
230;;; portability. As a result, it is possible to "forge" syntax
231;;; objects.
232
233;;; The implementation of generate-temporaries assumes that it is possible
234;;; to generate globally unique symbols (gensyms).
235
236;;; The input to sc-expand may contain "annotations" describing, e.g., the
237;;; source file and character position from where each object was read if
238;;; it was read from a file. These annotations are handled properly by
239;;; sc-expand only if the annotation? hook (see hooks below) is implemented
240;;; properly and the operators make-annotation, annotation-expression,
241;;; annotation-source, annotation-stripped, and set-annotation-stripped!
242;;; are supplied. If annotations are supplied, the proper annotation
243;;; source is passed to the various output constructors, allowing
244;;; implementations to accurately correlate source and expanded code.
245;;; Contact one of the authors for details if you wish to make use of
246;;; this feature.
247
248
249
250;;; Bootstrapping:
251
252;;; When changing syntax-object representations, it is necessary to support
253;;; both old and new syntax-object representations in id-var-name. It
254;;; should be sufficient to recognize old representations and treat
255;;; them as not lexically bound.
256
257
258
259(let ()
260(define-syntax define-structure
261 (lambda (x)
262 (define construct-name
263 (lambda (template-identifier . args)
264 (datum->syntax-object
265 template-identifier
266 (string->symbol
267 (apply string-append
268 (map (lambda (x)
269 (if (string? x)
270 x
271 (symbol->string (syntax-object->datum x))))
272 args))))))
273 (syntax-case x ()
274 ((_ (name id1 ...))
275 (andmap identifier? (syntax (name id1 ...)))
276 (with-syntax
277 ((constructor (construct-name (syntax name) "make-" (syntax name)))
278 (predicate (construct-name (syntax name) (syntax name) "?"))
279 ((access ...)
280 (map (lambda (x) (construct-name x (syntax name) "-" x))
281 (syntax (id1 ...))))
282 ((assign ...)
283 (map (lambda (x)
284 (construct-name x "set-" (syntax name) "-" x "!"))
285 (syntax (id1 ...))))
286 (structure-length
287 (+ (length (syntax (id1 ...))) 1))
288 ((index ...)
289 (let f ((i 1) (ids (syntax (id1 ...))))
290 (if (null? ids)
291 '()
292 (cons i (f (+ i 1) (cdr ids)))))))
293 (syntax (begin
294 (define constructor
295 (lambda (id1 ...)
296 (vector 'name id1 ... )))
297 (define predicate
298 (lambda (x)
299 (and (vector? x)
300 (= (vector-length x) structure-length)
301 (eq? (vector-ref x 0) 'name))))
302 (define access
303 (lambda (x)
304 (vector-ref x index)))
305 ...
306 (define assign
307 (lambda (x update)
308 (vector-set! x index update)))
309 ...)))))))
310
311(let ()
312(define noexpand "noexpand")
313
314;;; hooks to nonportable run-time helpers
315(begin
316(define fx+ +)
317(define fx- -)
318(define fx= =)
319(define fx< <)
320
a63812a2 321(define top-level-eval-hook
4e237f14 322 (lambda (x mod)
d2b61fe0
AW
323 (eval `(,noexpand ,x) (if mod (resolve-module mod)
324 (interaction-environment)))))
a63812a2
JB
325
326(define local-eval-hook
4e237f14 327 (lambda (x mod)
d2b61fe0
AW
328 (eval `(,noexpand ,x) (if mod (resolve-module mod)
329 (interaction-environment)))))
a63812a2
JB
330
331(define error-hook
332 (lambda (who why what)
333 (error who "~a ~s" why what)))
334
335(define-syntax gensym-hook
336 (syntax-rules ()
337 ((_) (gensym))))
338
339(define put-global-definition-hook
8e1d0d50 340 (lambda (symbol binding module)
d2b61fe0
AW
341 (let* ((module (if module
342 (resolve-module module)
343 (warn "wha" symbol (current-module))))
8e1d0d50
AW
344 (v (or (module-variable module symbol)
345 (let ((v (make-variable sc-macro)))
346 (module-add! module symbol v)
347 v))))
348 ;; Don't destroy Guile macros corresponding to primitive syntax
349 ;; when syncase boots.
350 (if (not (and (symbol-property symbol 'primitive-syntax)
351 (eq? module the-syncase-module)))
352 (variable-set! v sc-macro))
353 ;; Properties are tied to variable objects
354 (set-object-property! v '*sc-expander* binding))))
a63812a2
JB
355
356(define get-global-definition-hook
8e1d0d50 357 (lambda (symbol module)
d2b61fe0
AW
358 (let* ((module (if module
359 (resolve-module module)
360 (warn "wha" symbol (current-module))))
8e1d0d50
AW
361 (v (module-variable module symbol)))
362 (and v
363 (or (object-property v '*sc-expander*)
364 (and (variable-bound? v)
365 (macro? (variable-ref v))
366 (macro-transformer (variable-ref v)) ;non-primitive
367 guile-macro))))))
a63812a2
JB
368)
369
370
371;;; output constructors
35289f24
AW
372(define (build-annotated src exp)
373 (if (and src (not (annotation? exp)))
374 (make-annotation exp src #t)
375 exp))
376
a63812a2
JB
377(define-syntax build-application
378 (syntax-rules ()
379 ((_ source fun-exp arg-exps)
35289f24 380 (build-annotated source `(,fun-exp . ,arg-exps)))))
a63812a2
JB
381
382(define-syntax build-conditional
383 (syntax-rules ()
384 ((_ source test-exp then-exp else-exp)
35289f24 385 (build-annotated source `(if ,test-exp ,then-exp ,else-exp)))))
a63812a2
JB
386
387(define-syntax build-lexical-reference
388 (syntax-rules ()
389 ((_ type source var)
35289f24 390 (build-annotated source var))))
a63812a2
JB
391
392(define-syntax build-lexical-assignment
393 (syntax-rules ()
394 ((_ source var exp)
35289f24 395 (build-annotated source `(set! ,var ,exp)))))
a63812a2
JB
396
397(define-syntax build-global-reference
398 (syntax-rules ()
4e237f14 399 ((_ source var mod)
8e1d0d50 400 (build-annotated source
d2b61fe0 401 (make-module-ref mod var #f)))))
a63812a2
JB
402
403(define-syntax build-global-assignment
404 (syntax-rules ()
4e237f14 405 ((_ source var exp mod)
8e1d0d50 406 (build-annotated source
d2b61fe0 407 `(set! ,(make-module-ref mod var #f) ,exp)))))
a63812a2
JB
408
409(define-syntax build-global-definition
410 (syntax-rules ()
4e237f14 411 ((_ source var exp mod)
35289f24 412 (build-annotated source `(define ,var ,exp)))))
a63812a2
JB
413
414(define-syntax build-lambda
415 (syntax-rules ()
416 ((_ src vars exp)
35289f24 417 (build-annotated src `(lambda ,vars ,exp)))))
a63812a2 418
4e237f14 419;; FIXME: wingo: add modules here somehow?
a63812a2
JB
420(define-syntax build-primref
421 (syntax-rules ()
35289f24
AW
422 ((_ src name) (build-annotated src name))
423 ((_ src level name) (build-annotated src name))))
a63812a2 424
80f225df 425(define (build-data src exp)
93f26b7b
MD
426 (if (and (self-evaluating? exp)
427 (not (vector? exp)))
35289f24
AW
428 (build-annotated src exp)
429 (build-annotated src (list 'quote exp))))
a63812a2
JB
430
431(define build-sequence
432 (lambda (src exps)
433 (if (null? (cdr exps))
35289f24
AW
434 (build-annotated src (car exps))
435 (build-annotated src `(begin ,@exps)))))
a63812a2
JB
436
437(define build-let
438 (lambda (src vars val-exps body-exp)
439 (if (null? vars)
35289f24
AW
440 (build-annotated src body-exp)
441 (build-annotated src `(let ,(map list vars val-exps) ,body-exp)))))
a63812a2
JB
442
443(define build-named-let
444 (lambda (src vars val-exps body-exp)
445 (if (null? vars)
35289f24
AW
446 (build-annotated src body-exp)
447 (build-annotated src
448 `(let ,(car vars)
449 ,(map list (cdr vars) val-exps) ,body-exp)))))
a63812a2
JB
450
451(define build-letrec
452 (lambda (src vars val-exps body-exp)
453 (if (null? vars)
35289f24
AW
454 (build-annotated src body-exp)
455 (build-annotated src
456 `(letrec ,(map list vars val-exps) ,body-exp)))))
a63812a2 457
4e237f14 458;; FIXME: wingo: use make-lexical
a63812a2
JB
459(define-syntax build-lexical-var
460 (syntax-rules ()
35289f24 461 ((_ src id) (build-annotated src (gensym (symbol->string id))))))
a63812a2 462
e02e84de 463(define-structure (syntax-object expression wrap module))
a63812a2
JB
464
465(define-syntax unannotate
466 (syntax-rules ()
467 ((_ x)
468 (let ((e x))
469 (if (annotation? e)
470 (annotation-expression e)
471 e)))))
472
473(define-syntax no-source (identifier-syntax #f))
474
475(define source-annotation
476 (lambda (x)
477 (cond
478 ((annotation? x) (annotation-source x))
479 ((syntax-object? x) (source-annotation (syntax-object-expression x)))
480 (else no-source))))
481
482(define-syntax arg-check
483 (syntax-rules ()
484 ((_ pred? e who)
485 (let ((x e))
486 (if (not (pred? x)) (error-hook who "invalid argument" x))))))
487
488;;; compile-time environments
489
490;;; wrap and environment comprise two level mapping.
491;;; wrap : id --> label
492;;; env : label --> <element>
493
494;;; environments are represented in two parts: a lexical part and a global
495;;; part. The lexical part is a simple list of associations from labels
496;;; to bindings. The global part is implemented by
497;;; {put,get}-global-definition-hook and associates symbols with
498;;; bindings.
499
500;;; global (assumed global variable) and displaced-lexical (see below)
501;;; do not show up in any environment; instead, they are fabricated by
502;;; lookup when it finds no other bindings.
503
504;;; <environment> ::= ((<label> . <binding>)*)
505
506;;; identifier bindings include a type and a value
507
508;;; <binding> ::= (macro . <procedure>) macros
509;;; (core . <procedure>) core forms
80f225df 510;;; (external-macro . <procedure>) external-macro
a63812a2
JB
511;;; (begin) begin
512;;; (define) define
513;;; (define-syntax) define-syntax
514;;; (local-syntax . rec?) let-syntax/letrec-syntax
515;;; (eval-when) eval-when
516;;; (syntax . (<var> . <level>)) pattern variables
517;;; (global) assumed global variable
518;;; (lexical . <var>) lexical variables
519;;; (displaced-lexical) displaced lexicals
520;;; <level> ::= <nonnegative integer>
521;;; <var> ::= variable returned by build-lexical-var
522
523;;; a macro is a user-defined syntactic-form. a core is a system-defined
524;;; syntactic form. begin, define, define-syntax, and eval-when are
525;;; treated specially since they are sensitive to whether the form is
526;;; at top-level and (except for eval-when) can denote valid internal
527;;; definitions.
528
529;;; a pattern variable is a variable introduced by syntax-case and can
530;;; be referenced only within a syntax form.
531
532;;; any identifier for which no top-level syntax definition or local
533;;; binding of any kind has been seen is assumed to be a global
534;;; variable.
535
536;;; a lexical variable is a lambda- or letrec-bound variable.
537
538;;; a displaced-lexical identifier is a lexical identifier removed from
539;;; it's scope by the return of a syntax object containing the identifier.
540;;; a displaced lexical can also appear when a letrec-syntax-bound
541;;; keyword is referenced on the rhs of one of the letrec-syntax clauses.
542;;; a displaced lexical should never occur with properly written macros.
543
544(define-syntax make-binding
545 (syntax-rules (quote)
546 ((_ type value) (cons type value))
547 ((_ 'type) '(type))
548 ((_ type) (cons type '()))))
549(define binding-type car)
550(define binding-value cdr)
551
552(define-syntax null-env (identifier-syntax '()))
553
554(define extend-env
555 (lambda (labels bindings r)
556 (if (null? labels)
557 r
558 (extend-env (cdr labels) (cdr bindings)
559 (cons (cons (car labels) (car bindings)) r)))))
560
561(define extend-var-env
562 ; variant of extend-env that forms "lexical" binding
563 (lambda (labels vars r)
564 (if (null? labels)
565 r
566 (extend-var-env (cdr labels) (cdr vars)
567 (cons (cons (car labels) (make-binding 'lexical (car vars))) r)))))
568
569;;; we use a "macros only" environment in expansion of local macro
570;;; definitions so that their definitions can use local macros without
571;;; attempting to use other lexical identifiers.
572(define macros-only-env
573 (lambda (r)
574 (if (null? r)
575 '()
576 (let ((a (car r)))
577 (if (eq? (cadr a) 'macro)
578 (cons a (macros-only-env (cdr r)))
579 (macros-only-env (cdr r)))))))
580
581(define lookup
582 ; x may be a label or a symbol
583 ; although symbols are usually global, we check the environment first
584 ; anyway because a temporary binding may have been established by
585 ; fluid-let-syntax
8e1d0d50 586 (lambda (x r mod)
a63812a2
JB
587 (cond
588 ((assq x r) => cdr)
589 ((symbol? x)
8e1d0d50 590 (or (get-global-definition-hook x mod) (make-binding 'global)))
a63812a2
JB
591 (else (make-binding 'displaced-lexical)))))
592
593(define global-extend
594 (lambda (type sym val)
8e1d0d50 595 (put-global-definition-hook sym (make-binding type val)
d2b61fe0 596 (module-name (current-module)))))
a63812a2
JB
597
598
599;;; Conceptually, identifiers are always syntax objects. Internally,
600;;; however, the wrap is sometimes maintained separately (a source of
601;;; efficiency and confusion), so that symbols are also considered
602;;; identifiers by id?. Externally, they are always wrapped.
603
604(define nonsymbol-id?
605 (lambda (x)
606 (and (syntax-object? x)
607 (symbol? (unannotate (syntax-object-expression x))))))
608
609(define id?
610 (lambda (x)
611 (cond
612 ((symbol? x) #t)
613 ((syntax-object? x) (symbol? (unannotate (syntax-object-expression x))))
614 ((annotation? x) (symbol? (annotation-expression x)))
615 (else #f))))
616
617(define-syntax id-sym-name
618 (syntax-rules ()
619 ((_ e)
620 (let ((x e))
621 (unannotate (if (syntax-object? x) (syntax-object-expression x) x))))))
622
623(define id-sym-name&marks
624 (lambda (x w)
625 (if (syntax-object? x)
626 (values
627 (unannotate (syntax-object-expression x))
628 (join-marks (wrap-marks w) (wrap-marks (syntax-object-wrap x))))
629 (values (unannotate x) (wrap-marks w)))))
630
631;;; syntax object wraps
632
633;;; <wrap> ::= ((<mark> ...) . (<subst> ...))
634;;; <subst> ::= <shift> | <subs>
635;;; <subs> ::= #(<old name> <label> (<mark> ...))
636;;; <shift> ::= positive fixnum
637
638(define make-wrap cons)
639(define wrap-marks car)
640(define wrap-subst cdr)
641
642(define-syntax subst-rename? (identifier-syntax vector?))
643(define-syntax rename-old (syntax-rules () ((_ x) (vector-ref x 0))))
644(define-syntax rename-new (syntax-rules () ((_ x) (vector-ref x 1))))
645(define-syntax rename-marks (syntax-rules () ((_ x) (vector-ref x 2))))
646(define-syntax make-rename
647 (syntax-rules ()
648 ((_ old new marks) (vector old new marks))))
649
650;;; labels must be comparable with "eq?" and distinct from symbols.
651(define gen-label
652 (lambda () (string #\i)))
653
654(define gen-labels
655 (lambda (ls)
656 (if (null? ls)
657 '()
658 (cons (gen-label) (gen-labels (cdr ls))))))
659
660(define-structure (ribcage symnames marks labels))
661
662(define-syntax empty-wrap (identifier-syntax '(())))
663
664(define-syntax top-wrap (identifier-syntax '((top))))
665
666(define-syntax top-marked?
667 (syntax-rules ()
668 ((_ w) (memq 'top (wrap-marks w)))))
669
670;;; Marks must be comparable with "eq?" and distinct from pairs and
671;;; the symbol top. We do not use integers so that marks will remain
672;;; unique even across file compiles.
673
674(define-syntax the-anti-mark (identifier-syntax #f))
675
676(define anti-mark
677 (lambda (w)
678 (make-wrap (cons the-anti-mark (wrap-marks w))
679 (cons 'shift (wrap-subst w)))))
680
681(define-syntax new-mark
682 (syntax-rules ()
683 ((_) (string #\m))))
684
685;;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
686;;; internal definitions, in which the ribcages are built incrementally
687(define-syntax make-empty-ribcage
688 (syntax-rules ()
689 ((_) (make-ribcage '() '() '()))))
690
691(define extend-ribcage!
692 ; must receive ids with complete wraps
693 (lambda (ribcage id label)
694 (set-ribcage-symnames! ribcage
695 (cons (unannotate (syntax-object-expression id))
696 (ribcage-symnames ribcage)))
697 (set-ribcage-marks! ribcage
698 (cons (wrap-marks (syntax-object-wrap id))
699 (ribcage-marks ribcage)))
700 (set-ribcage-labels! ribcage
701 (cons label (ribcage-labels ribcage)))))
702
703;;; make-binding-wrap creates vector-based ribcages
704(define make-binding-wrap
705 (lambda (ids labels w)
706 (if (null? ids)
707 w
708 (make-wrap
709 (wrap-marks w)
710 (cons
711 (let ((labelvec (list->vector labels)))
712 (let ((n (vector-length labelvec)))
713 (let ((symnamevec (make-vector n)) (marksvec (make-vector n)))
714 (let f ((ids ids) (i 0))
715 (if (not (null? ids))
716 (call-with-values
717 (lambda () (id-sym-name&marks (car ids) w))
718 (lambda (symname marks)
719 (vector-set! symnamevec i symname)
720 (vector-set! marksvec i marks)
721 (f (cdr ids) (fx+ i 1))))))
722 (make-ribcage symnamevec marksvec labelvec))))
723 (wrap-subst w))))))
724
725(define smart-append
726 (lambda (m1 m2)
727 (if (null? m2)
728 m1
729 (append m1 m2))))
730
731(define join-wraps
732 (lambda (w1 w2)
733 (let ((m1 (wrap-marks w1)) (s1 (wrap-subst w1)))
734 (if (null? m1)
735 (if (null? s1)
736 w2
737 (make-wrap
738 (wrap-marks w2)
739 (smart-append s1 (wrap-subst w2))))
740 (make-wrap
741 (smart-append m1 (wrap-marks w2))
742 (smart-append s1 (wrap-subst w2)))))))
743
744(define join-marks
745 (lambda (m1 m2)
746 (smart-append m1 m2)))
747
748(define same-marks?
749 (lambda (x y)
750 (or (eq? x y)
751 (and (not (null? x))
752 (not (null? y))
753 (eq? (car x) (car y))
754 (same-marks? (cdr x) (cdr y))))))
755
756(define id-var-name
757 (lambda (id w)
758 (define-syntax first
759 (syntax-rules ()
760 ((_ e) (call-with-values (lambda () e) (lambda (x . ignore) x)))))
761 (define search
762 (lambda (sym subst marks)
763 (if (null? subst)
764 (values #f marks)
765 (let ((fst (car subst)))
766 (if (eq? fst 'shift)
767 (search sym (cdr subst) (cdr marks))
768 (let ((symnames (ribcage-symnames fst)))
769 (if (vector? symnames)
770 (search-vector-rib sym subst marks symnames fst)
771 (search-list-rib sym subst marks symnames fst))))))))
772 (define search-list-rib
773 (lambda (sym subst marks symnames ribcage)
774 (let f ((symnames symnames) (i 0))
775 (cond
776 ((null? symnames) (search sym (cdr subst) marks))
777 ((and (eq? (car symnames) sym)
778 (same-marks? marks (list-ref (ribcage-marks ribcage) i)))
779 (values (list-ref (ribcage-labels ribcage) i) marks))
780 (else (f (cdr symnames) (fx+ i 1)))))))
781 (define search-vector-rib
782 (lambda (sym subst marks symnames ribcage)
783 (let ((n (vector-length symnames)))
784 (let f ((i 0))
785 (cond
786 ((fx= i n) (search sym (cdr subst) marks))
787 ((and (eq? (vector-ref symnames i) sym)
788 (same-marks? marks (vector-ref (ribcage-marks ribcage) i)))
789 (values (vector-ref (ribcage-labels ribcage) i) marks))
790 (else (f (fx+ i 1))))))))
791 (cond
792 ((symbol? id)
793 (or (first (search id (wrap-subst w) (wrap-marks w))) id))
794 ((syntax-object? id)
795 (let ((id (unannotate (syntax-object-expression id)))
796 (w1 (syntax-object-wrap id)))
797 (let ((marks (join-marks (wrap-marks w) (wrap-marks w1))))
798 (call-with-values (lambda () (search id (wrap-subst w) marks))
799 (lambda (new-id marks)
800 (or new-id
801 (first (search id (wrap-subst w1) marks))
802 id))))))
803 ((annotation? id)
804 (let ((id (unannotate id)))
805 (or (first (search id (wrap-subst w) (wrap-marks w))) id)))
806 (else (error-hook 'id-var-name "invalid id" id)))))
807
808;;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
809;;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
810
811(define free-id=?
812 (lambda (i j)
813 (and (eq? (id-sym-name i) (id-sym-name j)) ; accelerator
814 (eq? (id-var-name i empty-wrap) (id-var-name j empty-wrap)))))
815
816;;; bound-id=? may be passed unwrapped (or partially wrapped) ids as
817;;; long as the missing portion of the wrap is common to both of the ids
818;;; since (bound-id=? x y) iff (bound-id=? (wrap x w) (wrap y w))
819
820(define bound-id=?
821 (lambda (i j)
822 (if (and (syntax-object? i) (syntax-object? j))
823 (and (eq? (unannotate (syntax-object-expression i))
824 (unannotate (syntax-object-expression j)))
825 (same-marks? (wrap-marks (syntax-object-wrap i))
826 (wrap-marks (syntax-object-wrap j))))
827 (eq? (unannotate i) (unannotate j)))))
828
829;;; "valid-bound-ids?" returns #t if it receives a list of distinct ids.
830;;; valid-bound-ids? may be passed unwrapped (or partially wrapped) ids
831;;; as long as the missing portion of the wrap is common to all of the
832;;; ids.
833
834(define valid-bound-ids?
835 (lambda (ids)
836 (and (let all-ids? ((ids ids))
837 (or (null? ids)
838 (and (id? (car ids))
839 (all-ids? (cdr ids)))))
840 (distinct-bound-ids? ids))))
841
842;;; distinct-bound-ids? expects a list of ids and returns #t if there are
843;;; no duplicates. It is quadratic on the length of the id list; long
844;;; lists could be sorted to make it more efficient. distinct-bound-ids?
845;;; may be passed unwrapped (or partially wrapped) ids as long as the
846;;; missing portion of the wrap is common to all of the ids.
847
848(define distinct-bound-ids?
849 (lambda (ids)
850 (let distinct? ((ids ids))
851 (or (null? ids)
852 (and (not (bound-id-member? (car ids) (cdr ids)))
853 (distinct? (cdr ids)))))))
854
855(define bound-id-member?
856 (lambda (x list)
857 (and (not (null? list))
858 (or (bound-id=? x (car list))
859 (bound-id-member? x (cdr list))))))
860
861;;; wrapping expressions and identifiers
862
863(define wrap
4e237f14 864 (lambda (x w defmod)
a63812a2
JB
865 (cond
866 ((and (null? (wrap-marks w)) (null? (wrap-subst w))) x)
867 ((syntax-object? x)
868 (make-syntax-object
869 (syntax-object-expression x)
e02e84de
AW
870 (join-wraps w (syntax-object-wrap x))
871 (syntax-object-module x)))
a63812a2 872 ((null? x) x)
4e237f14 873 (else (make-syntax-object x w defmod)))))
a63812a2
JB
874
875(define source-wrap
4e237f14
AW
876 (lambda (x w s defmod)
877 (wrap (if s (make-annotation x s #f) x) w defmod)))
a63812a2
JB
878
879;;; expanding
880
881(define chi-sequence
4e237f14 882 (lambda (body r w s mod)
a63812a2 883 (build-sequence s
4e237f14 884 (let dobody ((body body) (r r) (w w) (mod mod))
a63812a2
JB
885 (if (null? body)
886 '()
4e237f14
AW
887 (let ((first (chi (car body) r w mod)))
888 (cons first (dobody (cdr body) r w mod))))))))
a63812a2
JB
889
890(define chi-top-sequence
4e237f14 891 (lambda (body r w s m esew mod)
a63812a2 892 (build-sequence s
4e237f14 893 (let dobody ((body body) (r r) (w w) (m m) (esew esew) (mod mod))
a63812a2
JB
894 (if (null? body)
895 '()
4e237f14
AW
896 (let ((first (chi-top (car body) r w m esew mod)))
897 (cons first (dobody (cdr body) r w m esew mod))))))))
a63812a2 898
4e237f14 899;; FIXME: module?
a63812a2
JB
900(define chi-install-global
901 (lambda (name e)
902 (build-application no-source
903 (build-primref no-source 'install-global-transformer)
904 (list (build-data no-source name) e))))
905
906(define chi-when-list
907 (lambda (e when-list w)
908 ; when-list is syntax'd version of list of situations
909 (let f ((when-list when-list) (situations '()))
910 (if (null? when-list)
911 situations
912 (f (cdr when-list)
913 (cons (let ((x (car when-list)))
914 (cond
915 ((free-id=? x (syntax compile)) 'compile)
916 ((free-id=? x (syntax load)) 'load)
917 ((free-id=? x (syntax eval)) 'eval)
4e237f14 918 (else (syntax-error (wrap x w #f)
a63812a2
JB
919 "invalid eval-when situation"))))
920 situations))))))
921
4e237f14
AW
922;;; syntax-type returns six values: type, value, e, w, s, and mod. The
923;;; first two are described in the table below.
a63812a2
JB
924;;;
925;;; type value explanation
926;;; -------------------------------------------------------------------
927;;; core procedure core form (including singleton)
80f225df 928;;; external-macro procedure external macro
a63812a2
JB
929;;; lexical name lexical variable reference
930;;; global name global variable reference
931;;; begin none begin keyword
932;;; define none define keyword
933;;; define-syntax none define-syntax keyword
934;;; local-syntax rec? letrec-syntax/let-syntax keyword
935;;; eval-when none eval-when keyword
936;;; syntax level pattern variable
937;;; displaced-lexical none displaced lexical identifier
938;;; lexical-call name call to lexical variable
939;;; global-call name call to global variable
940;;; call none any other call
941;;; begin-form none begin expression
942;;; define-form id variable definition
943;;; define-syntax-form id syntax definition
944;;; local-syntax-form rec? syntax definition
945;;; eval-when-form none eval-when form
946;;; constant none self-evaluating datum
947;;; other none anything else
948;;;
949;;; For define-form and define-syntax-form, e is the rhs expression.
950;;; For all others, e is the entire form. w is the wrap for e.
4e237f14 951;;; s is the source for the entire form. mod is the module for e.
a63812a2
JB
952;;;
953;;; syntax-type expands macros and unwraps as necessary to get to
954;;; one of the forms above. It also parses define and define-syntax
955;;; forms, although perhaps this should be done by the consumer.
956
957(define syntax-type
4e237f14 958 (lambda (e r w s rib mod)
a63812a2
JB
959 (cond
960 ((symbol? e)
961 (let* ((n (id-var-name e w))
8e1d0d50 962 (b (lookup n r mod))
a63812a2
JB
963 (type (binding-type b)))
964 (case type
8e1d0d50 965 ((lexical) (values type (binding-value b) e w s mod))
4e237f14 966 ((global) (values type n e w s mod))
a63812a2 967 ((macro)
4e237f14
AW
968 (syntax-type (chi-macro (binding-value b) e r w rib mod)
969 r empty-wrap s rib mod))
970 (else (values type (binding-value b) e w s mod)))))
a63812a2
JB
971 ((pair? e)
972 (let ((first (car e)))
973 (if (id? first)
974 (let* ((n (id-var-name first w))
c5cc65ac
AW
975 (b (lookup n r (or (and (syntax-object? first)
976 (syntax-object-module first))
977 mod)))
a63812a2
JB
978 (type (binding-type b)))
979 (case type
4e237f14
AW
980 ((lexical)
981 (values 'lexical-call (binding-value b) e w s mod))
982 ((global)
983 (values 'global-call n e w s mod))
a63812a2 984 ((macro)
4e237f14
AW
985 (syntax-type (chi-macro (binding-value b) e r w rib mod)
986 r empty-wrap s rib mod))
987 ((core external-macro)
988 (values type (binding-value b) e w s mod))
a63812a2 989 ((local-syntax)
4e237f14
AW
990 (values 'local-syntax-form (binding-value b) e w s mod))
991 ((begin)
992 (values 'begin-form #f e w s mod))
993 ((eval-when)
994 (values 'eval-when-form #f e w s mod))
a63812a2
JB
995 ((define)
996 (syntax-case e ()
997 ((_ name val)
998 (id? (syntax name))
4e237f14 999 (values 'define-form (syntax name) (syntax val) w s mod))
a63812a2
JB
1000 ((_ (name . args) e1 e2 ...)
1001 (and (id? (syntax name))
1002 (valid-bound-ids? (lambda-var-list (syntax args))))
1003 ; need lambda here...
8e1d0d50 1004 (values 'define-form (wrap (syntax name) w mod)
4e237f14
AW
1005 (cons (syntax lambda) (wrap (syntax (args e1 e2 ...)) w mod))
1006 empty-wrap s mod))
a63812a2
JB
1007 ((_ name)
1008 (id? (syntax name))
8e1d0d50 1009 (values 'define-form (wrap (syntax name) w mod)
a63812a2 1010 (syntax (void))
4e237f14 1011 empty-wrap s mod))))
a63812a2
JB
1012 ((define-syntax)
1013 (syntax-case e ()
1014 ((_ name val)
1015 (id? (syntax name))
1016 (values 'define-syntax-form (syntax name)
4e237f14
AW
1017 (syntax val) w s mod))))
1018 (else
1019 (values 'call #f e w s mod))))
1020 (values 'call #f e w s mod))))
a63812a2
JB
1021 ((syntax-object? e)
1022 ;; s can't be valid source if we've unwrapped
1023 (syntax-type (syntax-object-expression e)
1024 r
1025 (join-wraps w (syntax-object-wrap e))
8e1d0d50 1026 no-source rib (or (syntax-object-module e) mod)))
a63812a2 1027 ((annotation? e)
4e237f14
AW
1028 (syntax-type (annotation-expression e) r w (annotation-source e) rib mod))
1029 ((self-evaluating? e) (values 'constant #f e w s mod))
1030 (else (values 'other #f e w s mod)))))
a63812a2
JB
1031
1032(define chi-top
4e237f14 1033 (lambda (e r w m esew mod)
a63812a2
JB
1034 (define-syntax eval-if-c&e
1035 (syntax-rules ()
4e237f14 1036 ((_ m e mod)
a63812a2 1037 (let ((x e))
4e237f14 1038 (if (eq? m 'c&e) (top-level-eval-hook x mod))
a63812a2
JB
1039 x))))
1040 (call-with-values
4e237f14
AW
1041 (lambda () (syntax-type e r w no-source #f mod))
1042 (lambda (type value e w s mod)
a63812a2
JB
1043 (case type
1044 ((begin-form)
1045 (syntax-case e ()
1046 ((_) (chi-void))
1047 ((_ e1 e2 ...)
4e237f14 1048 (chi-top-sequence (syntax (e1 e2 ...)) r w s m esew mod))))
a63812a2 1049 ((local-syntax-form)
4e237f14
AW
1050 (chi-local-syntax value e r w s mod
1051 (lambda (body r w s mod)
1052 (chi-top-sequence body r w s m esew mod))))
a63812a2
JB
1053 ((eval-when-form)
1054 (syntax-case e ()
1055 ((_ (x ...) e1 e2 ...)
1056 (let ((when-list (chi-when-list e (syntax (x ...)) w))
1057 (body (syntax (e1 e2 ...))))
1058 (cond
1059 ((eq? m 'e)
1060 (if (memq 'eval when-list)
4e237f14 1061 (chi-top-sequence body r w s 'e '(eval) mod)
a63812a2
JB
1062 (chi-void)))
1063 ((memq 'load when-list)
1064 (if (or (memq 'compile when-list)
1065 (and (eq? m 'c&e) (memq 'eval when-list)))
4e237f14 1066 (chi-top-sequence body r w s 'c&e '(compile load) mod)
a63812a2 1067 (if (memq m '(c c&e))
4e237f14 1068 (chi-top-sequence body r w s 'c '(load) mod)
a63812a2
JB
1069 (chi-void))))
1070 ((or (memq 'compile when-list)
1071 (and (eq? m 'c&e) (memq 'eval when-list)))
1072 (top-level-eval-hook
4e237f14
AW
1073 (chi-top-sequence body r w s 'e '(eval) mod)
1074 mod)
a63812a2
JB
1075 (chi-void))
1076 (else (chi-void)))))))
1077 ((define-syntax-form)
1078 (let ((n (id-var-name value w)) (r (macros-only-env r)))
1079 (case m
1080 ((c)
1081 (if (memq 'compile esew)
4e237f14
AW
1082 (let ((e (chi-install-global n (chi e r w mod))))
1083 (top-level-eval-hook e mod)
a63812a2
JB
1084 (if (memq 'load esew) e (chi-void)))
1085 (if (memq 'load esew)
4e237f14 1086 (chi-install-global n (chi e r w mod))
a63812a2
JB
1087 (chi-void))))
1088 ((c&e)
4e237f14
AW
1089 (let ((e (chi-install-global n (chi e r w mod))))
1090 (top-level-eval-hook e mod)
a63812a2
JB
1091 e))
1092 (else
1093 (if (memq 'eval esew)
1094 (top-level-eval-hook
4e237f14
AW
1095 (chi-install-global n (chi e r w mod))
1096 mod))
a63812a2
JB
1097 (chi-void)))))
1098 ((define-form)
80f225df 1099 (let* ((n (id-var-name value w))
8e1d0d50 1100 (type (binding-type (lookup n r mod))))
80f225df 1101 (case type
a63812a2
JB
1102 ((global)
1103 (eval-if-c&e m
4e237f14
AW
1104 (build-global-definition s n (chi e r w mod) mod)
1105 mod))
a63812a2 1106 ((displaced-lexical)
8e1d0d50 1107 (syntax-error (wrap value w mod) "identifier out of context"))
80f225df
MD
1108 (else
1109 (if (eq? type 'external-macro)
1110 (eval-if-c&e m
4e237f14
AW
1111 (build-global-definition s n (chi e r w mod) mod)
1112 mod)
8e1d0d50 1113 (syntax-error (wrap value w mod)
80f225df 1114 "cannot define keyword at top level"))))))
4e237f14 1115 (else (eval-if-c&e m (chi-expr type value e r w s mod) mod)))))))
a63812a2
JB
1116
1117(define chi
4e237f14 1118 (lambda (e r w mod)
a63812a2 1119 (call-with-values
4e237f14
AW
1120 (lambda () (syntax-type e r w no-source #f mod))
1121 (lambda (type value e w s mod)
1122 (chi-expr type value e r w s mod)))))
a63812a2
JB
1123
1124(define chi-expr
4e237f14 1125 (lambda (type value e r w s mod)
a63812a2
JB
1126 (case type
1127 ((lexical)
1128 (build-lexical-reference 'value s value))
4e237f14
AW
1129 ((core external-macro)
1130 ;; apply transformer
1131 (value e r w s mod))
a63812a2
JB
1132 ((lexical-call)
1133 (chi-application
1134 (build-lexical-reference 'fun (source-annotation (car e)) value)
4e237f14 1135 e r w s mod))
a63812a2
JB
1136 ((global-call)
1137 (chi-application
d2b61fe0
AW
1138 (build-global-reference (source-annotation (car e)) value
1139 (if (syntax-object? (car e))
1140 (syntax-object-module (car e))
1141 mod))
4e237f14
AW
1142 e r w s mod))
1143 ((constant) (build-data s (strip (source-wrap e w s mod) empty-wrap)))
1144 ((global) (build-global-reference s value mod))
1145 ((call) (chi-application (chi (car e) r w mod) e r w s mod))
a63812a2
JB
1146 ((begin-form)
1147 (syntax-case e ()
4e237f14 1148 ((_ e1 e2 ...) (chi-sequence (syntax (e1 e2 ...)) r w s mod))))
a63812a2 1149 ((local-syntax-form)
4e237f14 1150 (chi-local-syntax value e r w s mod chi-sequence))
a63812a2
JB
1151 ((eval-when-form)
1152 (syntax-case e ()
1153 ((_ (x ...) e1 e2 ...)
1154 (let ((when-list (chi-when-list e (syntax (x ...)) w)))
1155 (if (memq 'eval when-list)
4e237f14 1156 (chi-sequence (syntax (e1 e2 ...)) r w s mod)
a63812a2
JB
1157 (chi-void))))))
1158 ((define-form define-syntax-form)
8e1d0d50 1159 (syntax-error (wrap value w mod) "invalid context for definition of"))
a63812a2 1160 ((syntax)
4e237f14 1161 (syntax-error (source-wrap e w s mod)
a63812a2
JB
1162 "reference to pattern variable outside syntax form"))
1163 ((displaced-lexical)
4e237f14 1164 (syntax-error (source-wrap e w s mod)
a63812a2 1165 "reference to identifier outside its scope"))
4e237f14 1166 (else (syntax-error (source-wrap e w s mod))))))
a63812a2
JB
1167
1168(define chi-application
4e237f14 1169 (lambda (x e r w s mod)
a63812a2
JB
1170 (syntax-case e ()
1171 ((e0 e1 ...)
1172 (build-application s x
4e237f14 1173 (map (lambda (e) (chi e r w mod)) (syntax (e1 ...))))))))
a63812a2
JB
1174
1175(define chi-macro
4e237f14 1176 (lambda (p e r w rib mod)
a63812a2
JB
1177 (define rebuild-macro-output
1178 (lambda (x m)
1179 (cond ((pair? x)
1180 (cons (rebuild-macro-output (car x) m)
1181 (rebuild-macro-output (cdr x) m)))
1182 ((syntax-object? x)
1183 (let ((w (syntax-object-wrap x)))
1184 (let ((ms (wrap-marks w)) (s (wrap-subst w)))
4e237f14
AW
1185 (if (and (pair? ms) (eq? (car ms) the-anti-mark))
1186 ;; output is from original text
1187 (make-syntax-object
1188 (syntax-object-expression x)
1189 (make-wrap (cdr ms) (if rib (cons rib (cdr s)) (cdr s)))
1190 (syntax-object-module x))
1191 ;; output introduced by macro
1192 (make-syntax-object
1193 (syntax-object-expression x)
1194 (make-wrap (cons m ms)
1195 (if rib
1196 (cons rib (cons 'shift s))
1197 (cons 'shift s)))
d2b61fe0 1198 (module-name (procedure-module p))))))) ;; hither the hygiene
a63812a2
JB
1199 ((vector? x)
1200 (let* ((n (vector-length x)) (v (make-vector n)))
1201 (do ((i 0 (fx+ i 1)))
1202 ((fx= i n) v)
1203 (vector-set! v i
1204 (rebuild-macro-output (vector-ref x i) m)))))
1205 ((symbol? x)
1206 (syntax-error x "encountered raw symbol in macro output"))
1207 (else x))))
4e237f14 1208 (rebuild-macro-output (p (wrap e (anti-mark w) mod)) (new-mark))))
a63812a2
JB
1209
1210(define chi-body
1211 ;; In processing the forms of the body, we create a new, empty wrap.
1212 ;; This wrap is augmented (destructively) each time we discover that
1213 ;; the next form is a definition. This is done:
1214 ;;
1215 ;; (1) to allow the first nondefinition form to be a call to
1216 ;; one of the defined ids even if the id previously denoted a
1217 ;; definition keyword or keyword for a macro expanding into a
1218 ;; definition;
1219 ;; (2) to prevent subsequent definition forms (but unfortunately
1220 ;; not earlier ones) and the first nondefinition form from
1221 ;; confusing one of the bound identifiers for an auxiliary
1222 ;; keyword; and
1223 ;; (3) so that we do not need to restart the expansion of the
1224 ;; first nondefinition form, which is problematic anyway
1225 ;; since it might be the first element of a begin that we
1226 ;; have just spliced into the body (meaning if we restarted,
1227 ;; we'd really need to restart with the begin or the macro
1228 ;; call that expanded into the begin, and we'd have to give
1229 ;; up allowing (begin <defn>+ <expr>+), which is itself
1230 ;; problematic since we don't know if a begin contains only
1231 ;; definitions until we've expanded it).
1232 ;;
1233 ;; Before processing the body, we also create a new environment
1234 ;; containing a placeholder for the bindings we will add later and
1235 ;; associate this environment with each form. In processing a
1236 ;; let-syntax or letrec-syntax, the associated environment may be
1237 ;; augmented with local keyword bindings, so the environment may
1238 ;; be different for different forms in the body. Once we have
1239 ;; gathered up all of the definitions, we evaluate the transformer
1240 ;; expressions and splice into r at the placeholder the new variable
1241 ;; and keyword bindings. This allows let-syntax or letrec-syntax
1242 ;; forms local to a portion or all of the body to shadow the
1243 ;; definition bindings.
1244 ;;
1245 ;; Subforms of a begin, let-syntax, or letrec-syntax are spliced
1246 ;; into the body.
1247 ;;
1248 ;; outer-form is fully wrapped w/source
4e237f14 1249 (lambda (body outer-form r w mod)
a63812a2
JB
1250 (let* ((r (cons '("placeholder" . (placeholder)) r))
1251 (ribcage (make-empty-ribcage))
1252 (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
4e237f14 1253 (let parse ((body (map (lambda (x) (cons r (wrap x w mod))) body))
a63812a2
JB
1254 (ids '()) (labels '()) (vars '()) (vals '()) (bindings '()))
1255 (if (null? body)
1256 (syntax-error outer-form "no expressions in body")
1257 (let ((e (cdar body)) (er (caar body)))
1258 (call-with-values
4e237f14
AW
1259 (lambda () (syntax-type e er empty-wrap no-source ribcage mod))
1260 (lambda (type value e w s mod)
a63812a2
JB
1261 (case type
1262 ((define-form)
4e237f14 1263 (let ((id (wrap value w mod)) (label (gen-label)))
a63812a2
JB
1264 (let ((var (gen-var id)))
1265 (extend-ribcage! ribcage id label)
1266 (parse (cdr body)
1267 (cons id ids) (cons label labels)
4e237f14 1268 (cons var vars) (cons (cons er (wrap e w mod)) vals)
a63812a2
JB
1269 (cons (make-binding 'lexical var) bindings)))))
1270 ((define-syntax-form)
4e237f14 1271 (let ((id (wrap value w mod)) (label (gen-label)))
a63812a2
JB
1272 (extend-ribcage! ribcage id label)
1273 (parse (cdr body)
1274 (cons id ids) (cons label labels)
1275 vars vals
4e237f14 1276 (cons (make-binding 'macro (cons er (wrap e w mod)))
a63812a2
JB
1277 bindings))))
1278 ((begin-form)
1279 (syntax-case e ()
1280 ((_ e1 ...)
1281 (parse (let f ((forms (syntax (e1 ...))))
1282 (if (null? forms)
1283 (cdr body)
4e237f14 1284 (cons (cons er (wrap (car forms) w mod))
a63812a2
JB
1285 (f (cdr forms)))))
1286 ids labels vars vals bindings))))
1287 ((local-syntax-form)
4e237f14
AW
1288 (chi-local-syntax value e er w s mod
1289 (lambda (forms er w s mod)
a63812a2
JB
1290 (parse (let f ((forms forms))
1291 (if (null? forms)
1292 (cdr body)
4e237f14 1293 (cons (cons er (wrap (car forms) w mod))
a63812a2
JB
1294 (f (cdr forms)))))
1295 ids labels vars vals bindings))))
1296 (else ; found a non-definition
1297 (if (null? ids)
1298 (build-sequence no-source
1299 (map (lambda (x)
4e237f14
AW
1300 (chi (cdr x) (car x) empty-wrap mod))
1301 (cons (cons er (source-wrap e w s mod))
a63812a2
JB
1302 (cdr body))))
1303 (begin
1304 (if (not (valid-bound-ids? ids))
1305 (syntax-error outer-form
1306 "invalid or duplicate identifier in definition"))
1307 (let loop ((bs bindings) (er-cache #f) (r-cache #f))
1308 (if (not (null? bs))
1309 (let* ((b (car bs)))
1310 (if (eq? (car b) 'macro)
1311 (let* ((er (cadr b))
1312 (r-cache
1313 (if (eq? er er-cache)
1314 r-cache
1315 (macros-only-env er))))
1316 (set-cdr! b
1317 (eval-local-transformer
4e237f14
AW
1318 (chi (cddr b) r-cache empty-wrap mod)
1319 mod))
a63812a2
JB
1320 (loop (cdr bs) er r-cache))
1321 (loop (cdr bs) er-cache r-cache)))))
1322 (set-cdr! r (extend-env labels bindings (cdr r)))
1323 (build-letrec no-source
1324 vars
1325 (map (lambda (x)
4e237f14 1326 (chi (cdr x) (car x) empty-wrap mod))
a63812a2
JB
1327 vals)
1328 (build-sequence no-source
1329 (map (lambda (x)
4e237f14
AW
1330 (chi (cdr x) (car x) empty-wrap mod))
1331 (cons (cons er (source-wrap e w s mod))
a63812a2
JB
1332 (cdr body)))))))))))))))))
1333
1334(define chi-lambda-clause
4e237f14 1335 (lambda (e c r w mod k)
a63812a2
JB
1336 (syntax-case c ()
1337 (((id ...) e1 e2 ...)
1338 (let ((ids (syntax (id ...))))
1339 (if (not (valid-bound-ids? ids))
1340 (syntax-error e "invalid parameter list in")
1341 (let ((labels (gen-labels ids))
1342 (new-vars (map gen-var ids)))
1343 (k new-vars
1344 (chi-body (syntax (e1 e2 ...))
1345 e
1346 (extend-var-env labels new-vars r)
4e237f14
AW
1347 (make-binding-wrap ids labels w)
1348 mod))))))
a63812a2
JB
1349 ((ids e1 e2 ...)
1350 (let ((old-ids (lambda-var-list (syntax ids))))
1351 (if (not (valid-bound-ids? old-ids))
1352 (syntax-error e "invalid parameter list in")
1353 (let ((labels (gen-labels old-ids))
1354 (new-vars (map gen-var old-ids)))
1355 (k (let f ((ls1 (cdr new-vars)) (ls2 (car new-vars)))
1356 (if (null? ls1)
1357 ls2
1358 (f (cdr ls1) (cons (car ls1) ls2))))
1359 (chi-body (syntax (e1 e2 ...))
1360 e
1361 (extend-var-env labels new-vars r)
4e237f14
AW
1362 (make-binding-wrap old-ids labels w)
1363 mod))))))
a63812a2
JB
1364 (_ (syntax-error e)))))
1365
1366(define chi-local-syntax
4e237f14 1367 (lambda (rec? e r w s mod k)
a63812a2
JB
1368 (syntax-case e ()
1369 ((_ ((id val) ...) e1 e2 ...)
1370 (let ((ids (syntax (id ...))))
1371 (if (not (valid-bound-ids? ids))
1372 (syntax-error e "duplicate bound keyword in")
1373 (let ((labels (gen-labels ids)))
1374 (let ((new-w (make-binding-wrap ids labels w)))
1375 (k (syntax (e1 e2 ...))
1376 (extend-env
1377 labels
1378 (let ((w (if rec? new-w w))
1379 (trans-r (macros-only-env r)))
1380 (map (lambda (x)
1381 (make-binding 'macro
4e237f14
AW
1382 (eval-local-transformer
1383 (chi x trans-r w mod)
1384 mod)))
a63812a2
JB
1385 (syntax (val ...))))
1386 r)
1387 new-w
4e237f14
AW
1388 s
1389 mod))))))
1390 (_ (syntax-error (source-wrap e w s mod))))))
a63812a2
JB
1391
1392(define eval-local-transformer
4e237f14
AW
1393 (lambda (expanded mod)
1394 (let ((p (local-eval-hook expanded mod)))
a63812a2
JB
1395 (if (procedure? p)
1396 p
80f225df 1397 (syntax-error p "nonprocedure transformer")))))
a63812a2
JB
1398
1399(define chi-void
1400 (lambda ()
1401 (build-application no-source (build-primref no-source 'void) '())))
1402
1403(define ellipsis?
1404 (lambda (x)
1405 (and (nonsymbol-id? x)
1406 (free-id=? x (syntax (... ...))))))
1407
1408;;; data
1409
1410;;; strips all annotations from potentially circular reader output
1411
1412(define strip-annotation
1413 (lambda (x parent)
1414 (cond
1415 ((pair? x)
1416 (let ((new (cons #f #f)))
979933ab 1417 (if parent (set-annotation-stripped! parent new))
a63812a2
JB
1418 (set-car! new (strip-annotation (car x) #f))
1419 (set-cdr! new (strip-annotation (cdr x) #f))
1420 new))
1421 ((annotation? x)
1422 (or (annotation-stripped x)
1423 (strip-annotation (annotation-expression x) x)))
1424 ((vector? x)
1425 (let ((new (make-vector (vector-length x))))
979933ab 1426 (if parent (set-annotation-stripped! parent new))
a63812a2
JB
1427 (let loop ((i (- (vector-length x) 1)))
1428 (unless (fx< i 0)
1429 (vector-set! new i (strip-annotation (vector-ref x i) #f))
1430 (loop (fx- i 1))))
1431 new))
1432 (else x))))
1433
1434;;; strips syntax-objects down to top-wrap; if top-wrap is layered directly
1435;;; on an annotation, strips the annotation as well.
1436;;; since only the head of a list is annotated by the reader, not each pair
1437;;; in the spine, we also check for pairs whose cars are annotated in case
1438;;; we've been passed the cdr of an annotated list
1439
1440(define strip
1441 (lambda (x w)
1442 (if (top-marked? w)
1443 (if (or (annotation? x) (and (pair? x) (annotation? (car x))))
1444 (strip-annotation x #f)
1445 x)
1446 (let f ((x x))
1447 (cond
1448 ((syntax-object? x)
1449 (strip (syntax-object-expression x) (syntax-object-wrap x)))
1450 ((pair? x)
1451 (let ((a (f (car x))) (d (f (cdr x))))
1452 (if (and (eq? a (car x)) (eq? d (cdr x)))
1453 x
1454 (cons a d))))
1455 ((vector? x)
1456 (let ((old (vector->list x)))
1457 (let ((new (map f old)))
1458 (if (andmap eq? old new) x (list->vector new)))))
1459 (else x))))))
1460
1461;;; lexical variables
1462
1463(define gen-var
1464 (lambda (id)
1465 (let ((id (if (syntax-object? id) (syntax-object-expression id) id)))
1466 (if (annotation? id)
1467 (build-lexical-var (annotation-source id) (annotation-expression id))
1468 (build-lexical-var no-source id)))))
1469
1470(define lambda-var-list
1471 (lambda (vars)
1472 (let lvl ((vars vars) (ls '()) (w empty-wrap))
1473 (cond
4e237f14
AW
1474 ((pair? vars) (lvl (cdr vars) (cons (wrap (car vars) w #f) ls) w))
1475 ((id? vars) (cons (wrap vars w #f) ls))
a63812a2
JB
1476 ((null? vars) ls)
1477 ((syntax-object? vars)
1478 (lvl (syntax-object-expression vars)
1479 ls
1480 (join-wraps w (syntax-object-wrap vars))))
1481 ((annotation? vars)
1482 (lvl (annotation-expression vars) ls w))
1483 ; include anything else to be caught by subsequent error
1484 ; checking
1485 (else (cons vars ls))))))
1486
1487;;; core transformers
1488
1489(global-extend 'local-syntax 'letrec-syntax #t)
1490(global-extend 'local-syntax 'let-syntax #f)
1491
1492(global-extend 'core 'fluid-let-syntax
4e237f14 1493 (lambda (e r w s mod)
a63812a2
JB
1494 (syntax-case e ()
1495 ((_ ((var val) ...) e1 e2 ...)
1496 (valid-bound-ids? (syntax (var ...)))
1497 (let ((names (map (lambda (x) (id-var-name x w)) (syntax (var ...)))))
1498 (for-each
1499 (lambda (id n)
8e1d0d50 1500 (case (binding-type (lookup n r mod))
a63812a2 1501 ((displaced-lexical)
4e237f14 1502 (syntax-error (source-wrap id w s mod)
a63812a2
JB
1503 "identifier out of context"))))
1504 (syntax (var ...))
1505 names)
1506 (chi-body
1507 (syntax (e1 e2 ...))
4e237f14 1508 (source-wrap e w s mod)
a63812a2
JB
1509 (extend-env
1510 names
1511 (let ((trans-r (macros-only-env r)))
1512 (map (lambda (x)
1513 (make-binding 'macro
4e237f14
AW
1514 (eval-local-transformer (chi x trans-r w mod)
1515 mod)))
a63812a2
JB
1516 (syntax (val ...))))
1517 r)
4e237f14
AW
1518 w
1519 mod)))
1520 (_ (syntax-error (source-wrap e w s mod))))))
a63812a2
JB
1521
1522(global-extend 'core 'quote
4e237f14 1523 (lambda (e r w s mod)
a63812a2
JB
1524 (syntax-case e ()
1525 ((_ e) (build-data s (strip (syntax e) w)))
4e237f14 1526 (_ (syntax-error (source-wrap e w s mod))))))
a63812a2
JB
1527
1528(global-extend 'core 'syntax
1529 (let ()
1530 (define gen-syntax
8e1d0d50 1531 (lambda (src e r maps ellipsis? mod)
a63812a2
JB
1532 (if (id? e)
1533 (let ((label (id-var-name e empty-wrap)))
8e1d0d50 1534 (let ((b (lookup label r mod)))
a63812a2
JB
1535 (if (eq? (binding-type b) 'syntax)
1536 (call-with-values
1537 (lambda ()
1538 (let ((var.lev (binding-value b)))
1539 (gen-ref src (car var.lev) (cdr var.lev) maps)))
1540 (lambda (var maps) (values `(ref ,var) maps)))
1541 (if (ellipsis? e)
1542 (syntax-error src "misplaced ellipsis in syntax form")
1543 (values `(quote ,e) maps)))))
1544 (syntax-case e ()
1545 ((dots e)
1546 (ellipsis? (syntax dots))
8e1d0d50 1547 (gen-syntax src (syntax e) r maps (lambda (x) #f) mod))
a63812a2
JB
1548 ((x dots . y)
1549 ; this could be about a dozen lines of code, except that we
1550 ; choose to handle (syntax (x ... ...)) forms
1551 (ellipsis? (syntax dots))
1552 (let f ((y (syntax y))
1553 (k (lambda (maps)
1554 (call-with-values
1555 (lambda ()
1556 (gen-syntax src (syntax x) r
8e1d0d50 1557 (cons '() maps) ellipsis? mod))
a63812a2
JB
1558 (lambda (x maps)
1559 (if (null? (car maps))
1560 (syntax-error src
1561 "extra ellipsis in syntax form")
1562 (values (gen-map x (car maps))
1563 (cdr maps))))))))
1564 (syntax-case y ()
1565 ((dots . y)
1566 (ellipsis? (syntax dots))
1567 (f (syntax y)
1568 (lambda (maps)
1569 (call-with-values
1570 (lambda () (k (cons '() maps)))
1571 (lambda (x maps)
1572 (if (null? (car maps))
1573 (syntax-error src
1574 "extra ellipsis in syntax form")
1575 (values (gen-mappend x (car maps))
1576 (cdr maps))))))))
1577 (_ (call-with-values
8e1d0d50 1578 (lambda () (gen-syntax src y r maps ellipsis? mod))
a63812a2
JB
1579 (lambda (y maps)
1580 (call-with-values
1581 (lambda () (k maps))
1582 (lambda (x maps)
1583 (values (gen-append x y) maps)))))))))
1584 ((x . y)
1585 (call-with-values
8e1d0d50 1586 (lambda () (gen-syntax src (syntax x) r maps ellipsis? mod))
a63812a2
JB
1587 (lambda (x maps)
1588 (call-with-values
8e1d0d50 1589 (lambda () (gen-syntax src (syntax y) r maps ellipsis? mod))
a63812a2
JB
1590 (lambda (y maps) (values (gen-cons x y) maps))))))
1591 (#(e1 e2 ...)
1592 (call-with-values
1593 (lambda ()
8e1d0d50 1594 (gen-syntax src (syntax (e1 e2 ...)) r maps ellipsis? mod))
a63812a2
JB
1595 (lambda (e maps) (values (gen-vector e) maps))))
1596 (_ (values `(quote ,e) maps))))))
1597
1598 (define gen-ref
1599 (lambda (src var level maps)
1600 (if (fx= level 0)
1601 (values var maps)
1602 (if (null? maps)
1603 (syntax-error src "missing ellipsis in syntax form")
1604 (call-with-values
1605 (lambda () (gen-ref src var (fx- level 1) (cdr maps)))
1606 (lambda (outer-var outer-maps)
1607 (let ((b (assq outer-var (car maps))))
1608 (if b
1609 (values (cdr b) maps)
1610 (let ((inner-var (gen-var 'tmp)))
1611 (values inner-var
1612 (cons (cons (cons outer-var inner-var)
1613 (car maps))
1614 outer-maps)))))))))))
1615
1616 (define gen-mappend
1617 (lambda (e map-env)
1618 `(apply (primitive append) ,(gen-map e map-env))))
1619
1620 (define gen-map
1621 (lambda (e map-env)
1622 (let ((formals (map cdr map-env))
1623 (actuals (map (lambda (x) `(ref ,(car x))) map-env)))
1624 (cond
1625 ((eq? (car e) 'ref)
1626 ; identity map equivalence:
1627 ; (map (lambda (x) x) y) == y
1628 (car actuals))
1629 ((andmap
1630 (lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
1631 (cdr e))
1632 ; eta map equivalence:
1633 ; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
1634 `(map (primitive ,(car e))
1635 ,@(map (let ((r (map cons formals actuals)))
1636 (lambda (x) (cdr (assq (cadr x) r))))
1637 (cdr e))))
1638 (else `(map (lambda ,formals ,e) ,@actuals))))))
1639
1640 (define gen-cons
1641 (lambda (x y)
1642 (case (car y)
1643 ((quote)
1644 (if (eq? (car x) 'quote)
1645 `(quote (,(cadr x) . ,(cadr y)))
1646 (if (eq? (cadr y) '())
1647 `(list ,x)
1648 `(cons ,x ,y))))
1649 ((list) `(list ,x ,@(cdr y)))
1650 (else `(cons ,x ,y)))))
1651
1652 (define gen-append
1653 (lambda (x y)
1654 (if (equal? y '(quote ()))
1655 x
1656 `(append ,x ,y))))
1657
1658 (define gen-vector
1659 (lambda (x)
1660 (cond
1661 ((eq? (car x) 'list) `(vector ,@(cdr x)))
1662 ((eq? (car x) 'quote) `(quote #(,@(cadr x))))
1663 (else `(list->vector ,x)))))
1664
1665
1666 (define regen
1667 (lambda (x)
1668 (case (car x)
1669 ((ref) (build-lexical-reference 'value no-source (cadr x)))
1670 ((primitive) (build-primref no-source (cadr x)))
1671 ((quote) (build-data no-source (cadr x)))
1672 ((lambda) (build-lambda no-source (cadr x) (regen (caddr x))))
1673 ((map) (let ((ls (map regen (cdr x))))
1674 (build-application no-source
1675 (if (fx= (length ls) 2)
1676 (build-primref no-source 'map)
1677 ; really need to do our own checking here
1678 (build-primref no-source 2 'map)) ; require error check
1679 ls)))
1680 (else (build-application no-source
1681 (build-primref no-source (car x))
1682 (map regen (cdr x)))))))
1683
4e237f14
AW
1684 (lambda (e r w s mod)
1685 (let ((e (source-wrap e w s mod)))
a63812a2
JB
1686 (syntax-case e ()
1687 ((_ x)
1688 (call-with-values
8e1d0d50 1689 (lambda () (gen-syntax e (syntax x) r '() ellipsis? mod))
a63812a2
JB
1690 (lambda (e maps) (regen e))))
1691 (_ (syntax-error e)))))))
1692
1693
1694(global-extend 'core 'lambda
4e237f14 1695 (lambda (e r w s mod)
a63812a2
JB
1696 (syntax-case e ()
1697 ((_ . c)
4e237f14 1698 (chi-lambda-clause (source-wrap e w s mod) (syntax c) r w mod
a63812a2
JB
1699 (lambda (vars body) (build-lambda s vars body)))))))
1700
1701
1702(global-extend 'core 'let
1703 (let ()
4e237f14 1704 (define (chi-let e r w s mod constructor ids vals exps)
a63812a2
JB
1705 (if (not (valid-bound-ids? ids))
1706 (syntax-error e "duplicate bound variable in")
1707 (let ((labels (gen-labels ids))
1708 (new-vars (map gen-var ids)))
1709 (let ((nw (make-binding-wrap ids labels w))
1710 (nr (extend-var-env labels new-vars r)))
1711 (constructor s
1712 new-vars
4e237f14
AW
1713 (map (lambda (x) (chi x r w mod)) vals)
1714 (chi-body exps (source-wrap e nw s mod)
1715 nr nw mod))))))
1716 (lambda (e r w s mod)
a63812a2
JB
1717 (syntax-case e ()
1718 ((_ ((id val) ...) e1 e2 ...)
4e237f14 1719 (chi-let e r w s mod
a63812a2
JB
1720 build-let
1721 (syntax (id ...))
1722 (syntax (val ...))
1723 (syntax (e1 e2 ...))))
1724 ((_ f ((id val) ...) e1 e2 ...)
1725 (id? (syntax f))
4e237f14 1726 (chi-let e r w s mod
a63812a2
JB
1727 build-named-let
1728 (syntax (f id ...))
1729 (syntax (val ...))
1730 (syntax (e1 e2 ...))))
4e237f14 1731 (_ (syntax-error (source-wrap e w s mod)))))))
a63812a2
JB
1732
1733
1734(global-extend 'core 'letrec
4e237f14 1735 (lambda (e r w s mod)
a63812a2
JB
1736 (syntax-case e ()
1737 ((_ ((id val) ...) e1 e2 ...)
1738 (let ((ids (syntax (id ...))))
1739 (if (not (valid-bound-ids? ids))
1740 (syntax-error e "duplicate bound variable in")
1741 (let ((labels (gen-labels ids))
1742 (new-vars (map gen-var ids)))
1743 (let ((w (make-binding-wrap ids labels w))
1744 (r (extend-var-env labels new-vars r)))
1745 (build-letrec s
1746 new-vars
4e237f14
AW
1747 (map (lambda (x) (chi x r w mod)) (syntax (val ...)))
1748 (chi-body (syntax (e1 e2 ...))
1749 (source-wrap e w s mod) r w mod)))))))
1750 (_ (syntax-error (source-wrap e w s mod))))))
a63812a2
JB
1751
1752
1753(global-extend 'core 'set!
4e237f14 1754 (lambda (e r w s mod)
a63812a2
JB
1755 (syntax-case e ()
1756 ((_ id val)
1757 (id? (syntax id))
4e237f14 1758 (let ((val (chi (syntax val) r w mod))
a63812a2 1759 (n (id-var-name (syntax id) w)))
8e1d0d50 1760 (let ((b (lookup n r mod)))
a63812a2
JB
1761 (case (binding-type b)
1762 ((lexical)
1763 (build-lexical-assignment s (binding-value b) val))
4e237f14 1764 ((global) (build-global-assignment s n val mod))
a63812a2 1765 ((displaced-lexical)
8e1d0d50 1766 (syntax-error (wrap (syntax id) w mod)
a63812a2 1767 "identifier out of context"))
4e237f14 1768 (else (syntax-error (source-wrap e w s mod)))))))
fde75b7c
MD
1769 ((_ (getter arg ...) val)
1770 (build-application s
4e237f14
AW
1771 (chi (syntax (setter getter)) r w mod)
1772 (map (lambda (e) (chi e r w mod))
fde75b7c 1773 (syntax (arg ... val)))))
4e237f14 1774 (_ (syntax-error (source-wrap e w s mod))))))
a63812a2
JB
1775
1776(global-extend 'begin 'begin '())
1777
1778(global-extend 'define 'define '())
1779
1780(global-extend 'define-syntax 'define-syntax '())
1781
1782(global-extend 'eval-when 'eval-when '())
1783
1784(global-extend 'core 'syntax-case
1785 (let ()
1786 (define convert-pattern
1787 ; accepts pattern & keys
1788 ; returns syntax-dispatch pattern & ids
1789 (lambda (pattern keys)
1790 (let cvt ((p pattern) (n 0) (ids '()))
1791 (if (id? p)
1792 (if (bound-id-member? p keys)
1793 (values (vector 'free-id p) ids)
1794 (values 'any (cons (cons p n) ids)))
1795 (syntax-case p ()
1796 ((x dots)
1797 (ellipsis? (syntax dots))
1798 (call-with-values
1799 (lambda () (cvt (syntax x) (fx+ n 1) ids))
1800 (lambda (p ids)
1801 (values (if (eq? p 'any) 'each-any (vector 'each p))
1802 ids))))
1803 ((x . y)
1804 (call-with-values
1805 (lambda () (cvt (syntax y) n ids))
1806 (lambda (y ids)
1807 (call-with-values
1808 (lambda () (cvt (syntax x) n ids))
1809 (lambda (x ids)
1810 (values (cons x y) ids))))))
1811 (() (values '() ids))
1812 (#(x ...)
1813 (call-with-values
1814 (lambda () (cvt (syntax (x ...)) n ids))
1815 (lambda (p ids) (values (vector 'vector p) ids))))
1816 (x (values (vector 'atom (strip p empty-wrap)) ids)))))))
1817
1818 (define build-dispatch-call
4e237f14 1819 (lambda (pvars exp y r mod)
a63812a2
JB
1820 (let ((ids (map car pvars)) (levels (map cdr pvars)))
1821 (let ((labels (gen-labels ids)) (new-vars (map gen-var ids)))
1822 (build-application no-source
1823 (build-primref no-source 'apply)
1824 (list (build-lambda no-source new-vars
1825 (chi exp
4e237f14
AW
1826 (extend-env
1827 labels
1828 (map (lambda (var level)
1829 (make-binding 'syntax `(,var . ,level)))
1830 new-vars
1831 (map cdr pvars))
1832 r)
1833 (make-binding-wrap ids labels empty-wrap)
1834 mod))
a63812a2
JB
1835 y))))))
1836
1837 (define gen-clause
4e237f14 1838 (lambda (x keys clauses r pat fender exp mod)
a63812a2
JB
1839 (call-with-values
1840 (lambda () (convert-pattern pat keys))
1841 (lambda (p pvars)
1842 (cond
1843 ((not (distinct-bound-ids? (map car pvars)))
1844 (syntax-error pat
1845 "duplicate pattern variable in syntax-case pattern"))
1846 ((not (andmap (lambda (x) (not (ellipsis? (car x)))) pvars))
1847 (syntax-error pat
1848 "misplaced ellipsis in syntax-case pattern"))
1849 (else
1850 (let ((y (gen-var 'tmp)))
1851 ; fat finger binding and references to temp variable y
1852 (build-application no-source
1853 (build-lambda no-source (list y)
1854 (let ((y (build-lexical-reference 'value no-source y)))
1855 (build-conditional no-source
1856 (syntax-case fender ()
1857 (#t y)
1858 (_ (build-conditional no-source
1859 y
4e237f14 1860 (build-dispatch-call pvars fender y r mod)
a63812a2 1861 (build-data no-source #f))))
4e237f14
AW
1862 (build-dispatch-call pvars exp y r mod)
1863 (gen-syntax-case x keys clauses r mod))))
a63812a2
JB
1864 (list (if (eq? p 'any)
1865 (build-application no-source
1866 (build-primref no-source 'list)
1867 (list x))
1868 (build-application no-source
1869 (build-primref no-source 'syntax-dispatch)
1870 (list x (build-data no-source p)))))))))))))
1871
1872 (define gen-syntax-case
4e237f14 1873 (lambda (x keys clauses r mod)
a63812a2
JB
1874 (if (null? clauses)
1875 (build-application no-source
1876 (build-primref no-source 'syntax-error)
1877 (list x))
1878 (syntax-case (car clauses) ()
1879 ((pat exp)
1880 (if (and (id? (syntax pat))
1881 (andmap (lambda (x) (not (free-id=? (syntax pat) x)))
1882 (cons (syntax (... ...)) keys)))
1883 (let ((labels (list (gen-label)))
1884 (var (gen-var (syntax pat))))
1885 (build-application no-source
1886 (build-lambda no-source (list var)
1887 (chi (syntax exp)
1888 (extend-env labels
1889 (list (make-binding 'syntax `(,var . 0)))
1890 r)
1891 (make-binding-wrap (syntax (pat))
4e237f14
AW
1892 labels empty-wrap)
1893 mod))
a63812a2
JB
1894 (list x)))
1895 (gen-clause x keys (cdr clauses) r
4e237f14 1896 (syntax pat) #t (syntax exp) mod)))
a63812a2
JB
1897 ((pat fender exp)
1898 (gen-clause x keys (cdr clauses) r
4e237f14 1899 (syntax pat) (syntax fender) (syntax exp) mod))
a63812a2
JB
1900 (_ (syntax-error (car clauses) "invalid syntax-case clause"))))))
1901
4e237f14
AW
1902 (lambda (e r w s mod)
1903 (let ((e (source-wrap e w s mod)))
a63812a2
JB
1904 (syntax-case e ()
1905 ((_ val (key ...) m ...)
1906 (if (andmap (lambda (x) (and (id? x) (not (ellipsis? x))))
1907 (syntax (key ...)))
1908 (let ((x (gen-var 'tmp)))
1909 ; fat finger binding and references to temp variable x
1910 (build-application s
1911 (build-lambda no-source (list x)
1912 (gen-syntax-case (build-lexical-reference 'value no-source x)
1913 (syntax (key ...)) (syntax (m ...))
4e237f14
AW
1914 r
1915 mod))
1916 (list (chi (syntax val) r empty-wrap mod))))
a63812a2
JB
1917 (syntax-error e "invalid literals list in"))))))))
1918
1919;;; The portable sc-expand seeds chi-top's mode m with 'e (for
1920;;; evaluating) and esew (which stands for "eval syntax expanders
1921;;; when") with '(eval). In Chez Scheme, m is set to 'c instead of e
1922;;; if we are compiling a file, and esew is set to
1923;;; (eval-syntactic-expanders-when), which defaults to the list
1924;;; '(compile load eval). This means that, by default, top-level
1925;;; syntactic definitions are evaluated immediately after they are
1926;;; expanded, and the expanded definitions are also residualized into
1927;;; the object file if we are compiling a file.
1928(set! sc-expand
1929 (let ((m 'e) (esew '(eval)))
1930 (lambda (x)
1931 (if (and (pair? x) (equal? (car x) noexpand))
1932 (cadr x)
d2b61fe0
AW
1933 (chi-top x null-env top-wrap m esew
1934 (module-name (current-module)))))))
a63812a2
JB
1935
1936(set! sc-expand3
1937 (let ((m 'e) (esew '(eval)))
1938 (lambda (x . rest)
1939 (if (and (pair? x) (equal? (car x) noexpand))
1940 (cadr x)
1941 (chi-top x
1942 null-env
1943 top-wrap
1944 (if (null? rest) m (car rest))
1945 (if (or (null? rest) (null? (cdr rest)))
1946 esew
4e237f14 1947 (cadr rest))
d2b61fe0 1948 (module-name (current-module)))))))
a63812a2
JB
1949
1950(set! identifier?
1951 (lambda (x)
1952 (nonsymbol-id? x)))
1953
1954(set! datum->syntax-object
1955 (lambda (id datum)
e02e84de 1956 (make-syntax-object datum (syntax-object-wrap id) #f)))
a63812a2
JB
1957
1958(set! syntax-object->datum
1959 ; accepts any object, since syntax objects may consist partially
1960 ; or entirely of unwrapped, nonsymbolic data
1961 (lambda (x)
1962 (strip x empty-wrap)))
1963
1964(set! generate-temporaries
1965 (lambda (ls)
1966 (arg-check list? ls 'generate-temporaries)
4e237f14 1967 (map (lambda (x) (wrap (gensym-hook) top-wrap #f)) ls)))
a63812a2
JB
1968
1969(set! free-identifier=?
1970 (lambda (x y)
1971 (arg-check nonsymbol-id? x 'free-identifier=?)
1972 (arg-check nonsymbol-id? y 'free-identifier=?)
1973 (free-id=? x y)))
1974
1975(set! bound-identifier=?
1976 (lambda (x y)
1977 (arg-check nonsymbol-id? x 'bound-identifier=?)
1978 (arg-check nonsymbol-id? y 'bound-identifier=?)
1979 (bound-id=? x y)))
1980
1981(set! syntax-error
1982 (lambda (object . messages)
1983 (for-each (lambda (x) (arg-check string? x 'syntax-error)) messages)
1984 (let ((message (if (null? messages)
1985 "invalid syntax"
1986 (apply string-append messages))))
1987 (error-hook #f message (strip object empty-wrap)))))
1988
1989(set! install-global-transformer
1990 (lambda (sym v)
1991 (arg-check symbol? sym 'define-syntax)
1992 (arg-check procedure? v 'define-syntax)
1993 (global-extend 'macro sym v)))
1994
1995;;; syntax-dispatch expects an expression and a pattern. If the expression
1996;;; matches the pattern a list of the matching expressions for each
1997;;; "any" is returned. Otherwise, #f is returned. (This use of #f will
1998;;; not work on r4rs implementations that violate the ieee requirement
1999;;; that #f and () be distinct.)
2000
2001;;; The expression is matched with the pattern as follows:
2002
2003;;; pattern: matches:
2004;;; () empty list
2005;;; any anything
2006;;; (<pattern>1 . <pattern>2) (<pattern>1 . <pattern>2)
2007;;; each-any (any*)
2008;;; #(free-id <key>) <key> with free-identifier=?
2009;;; #(each <pattern>) (<pattern>*)
2010;;; #(vector <pattern>) (list->vector <pattern>)
2011;;; #(atom <object>) <object> with "equal?"
2012
2013;;; Vector cops out to pair under assumption that vectors are rare. If
2014;;; not, should convert to:
2015;;; #(vector <pattern>*) #(<pattern>*)
2016
2017(let ()
2018
2019(define match-each
d2b61fe0 2020 (lambda (e p w mod)
a63812a2
JB
2021 (cond
2022 ((annotation? e)
d2b61fe0 2023 (match-each (annotation-expression e) p w mod))
a63812a2 2024 ((pair? e)
d2b61fe0 2025 (let ((first (match (car e) p w '() mod)))
a63812a2 2026 (and first
d2b61fe0 2027 (let ((rest (match-each (cdr e) p w mod)))
a63812a2
JB
2028 (and rest (cons first rest))))))
2029 ((null? e) '())
2030 ((syntax-object? e)
2031 (match-each (syntax-object-expression e)
2032 p
d2b61fe0
AW
2033 (join-wraps w (syntax-object-wrap e))
2034 (syntax-object-module e)))
a63812a2
JB
2035 (else #f))))
2036
2037(define match-each-any
d2b61fe0 2038 (lambda (e w mod)
a63812a2
JB
2039 (cond
2040 ((annotation? e)
d2b61fe0 2041 (match-each-any (annotation-expression e) w mod))
a63812a2 2042 ((pair? e)
d2b61fe0
AW
2043 (let ((l (match-each-any (cdr e) w mod)))
2044 (and l (cons (wrap (car e) w mod) l))))
a63812a2
JB
2045 ((null? e) '())
2046 ((syntax-object? e)
2047 (match-each-any (syntax-object-expression e)
d2b61fe0
AW
2048 (join-wraps w (syntax-object-wrap e))
2049 mod))
a63812a2
JB
2050 (else #f))))
2051
2052(define match-empty
2053 (lambda (p r)
2054 (cond
2055 ((null? p) r)
2056 ((eq? p 'any) (cons '() r))
2057 ((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
2058 ((eq? p 'each-any) (cons '() r))
2059 (else
2060 (case (vector-ref p 0)
2061 ((each) (match-empty (vector-ref p 1) r))
2062 ((free-id atom) r)
2063 ((vector) (match-empty (vector-ref p 1) r)))))))
2064
2065(define match*
d2b61fe0 2066 (lambda (e p w r mod)
a63812a2
JB
2067 (cond
2068 ((null? p) (and (null? e) r))
2069 ((pair? p)
2070 (and (pair? e) (match (car e) (car p) w
d2b61fe0
AW
2071 (match (cdr e) (cdr p) w r mod)
2072 mod)))
a63812a2 2073 ((eq? p 'each-any)
d2b61fe0 2074 (let ((l (match-each-any e w mod))) (and l (cons l r))))
a63812a2
JB
2075 (else
2076 (case (vector-ref p 0)
2077 ((each)
2078 (if (null? e)
2079 (match-empty (vector-ref p 1) r)
d2b61fe0 2080 (let ((l (match-each e (vector-ref p 1) w mod)))
a63812a2
JB
2081 (and l
2082 (let collect ((l l))
2083 (if (null? (car l))
2084 r
2085 (cons (map car l) (collect (map cdr l)))))))))
d2b61fe0 2086 ((free-id) (and (id? e) (free-id=? (wrap e w mod) (vector-ref p 1)) r))
a63812a2
JB
2087 ((atom) (and (equal? (vector-ref p 1) (strip e w)) r))
2088 ((vector)
2089 (and (vector? e)
d2b61fe0 2090 (match (vector->list e) (vector-ref p 1) w r mod))))))))
a63812a2
JB
2091
2092(define match
d2b61fe0 2093 (lambda (e p w r mod)
a63812a2
JB
2094 (cond
2095 ((not r) #f)
d2b61fe0 2096 ((eq? p 'any) (cons (wrap e w mod) r))
a63812a2
JB
2097 ((syntax-object? e)
2098 (match*
2099 (unannotate (syntax-object-expression e))
2100 p
2101 (join-wraps w (syntax-object-wrap e))
d2b61fe0
AW
2102 r
2103 (syntax-object-module e)))
2104 (else (match* (unannotate e) p w r mod)))))
a63812a2
JB
2105
2106(set! syntax-dispatch
2107 (lambda (e p)
2108 (cond
2109 ((eq? p 'any) (list e))
2110 ((syntax-object? e)
2111 (match* (unannotate (syntax-object-expression e))
d2b61fe0
AW
2112 p (syntax-object-wrap e) '() (syntax-object-module e)))
2113 (else (match* (unannotate e) p empty-wrap '() #f)))))
80f225df
MD
2114
2115(set! sc-chi chi)
a63812a2
JB
2116))
2117)
2118
2119(define-syntax with-syntax
2120 (lambda (x)
2121 (syntax-case x ()
2122 ((_ () e1 e2 ...)
2123 (syntax (begin e1 e2 ...)))
2124 ((_ ((out in)) e1 e2 ...)
2125 (syntax (syntax-case in () (out (begin e1 e2 ...)))))
2126 ((_ ((out in) ...) e1 e2 ...)
2127 (syntax (syntax-case (list in ...) ()
2128 ((out ...) (begin e1 e2 ...))))))))
2129
2130(define-syntax syntax-rules
2131 (lambda (x)
2132 (syntax-case x ()
2133 ((_ (k ...) ((keyword . pattern) template) ...)
2134 (syntax (lambda (x)
2135 (syntax-case x (k ...)
2136 ((dummy . pattern) (syntax template))
2137 ...)))))))
2138
2139(define-syntax let*
2140 (lambda (x)
2141 (syntax-case x ()
2142 ((let* ((x v) ...) e1 e2 ...)
2143 (andmap identifier? (syntax (x ...)))
2144 (let f ((bindings (syntax ((x v) ...))))
2145 (if (null? bindings)
2146 (syntax (let () e1 e2 ...))
2147 (with-syntax ((body (f (cdr bindings)))
2148 (binding (car bindings)))
2149 (syntax (let (binding) body)))))))))
2150
2151(define-syntax do
2152 (lambda (orig-x)
2153 (syntax-case orig-x ()
2154 ((_ ((var init . step) ...) (e0 e1 ...) c ...)
2155 (with-syntax (((step ...)
2156 (map (lambda (v s)
2157 (syntax-case s ()
2158 (() v)
2159 ((e) (syntax e))
2160 (_ (syntax-error orig-x))))
2161 (syntax (var ...))
2162 (syntax (step ...)))))
2163 (syntax-case (syntax (e1 ...)) ()
2164 (() (syntax (let doloop ((var init) ...)
2165 (if (not e0)
2166 (begin c ... (doloop step ...))))))
2167 ((e1 e2 ...)
2168 (syntax (let doloop ((var init) ...)
2169 (if e0
2170 (begin e1 e2 ...)
2171 (begin c ... (doloop step ...))))))))))))
2172
2173(define-syntax quasiquote
2174 (letrec
2175 ((quasicons
2176 (lambda (x y)
2177 (with-syntax ((x x) (y y))
2178 (syntax-case (syntax y) (quote list)
2179 ((quote dy)
2180 (syntax-case (syntax x) (quote)
2181 ((quote dx) (syntax (quote (dx . dy))))
2182 (_ (if (null? (syntax dy))
2183 (syntax (list x))
2184 (syntax (cons x y))))))
2185 ((list . stuff) (syntax (list x . stuff)))
2186 (else (syntax (cons x y)))))))
2187 (quasiappend
2188 (lambda (x y)
2189 (with-syntax ((x x) (y y))
2190 (syntax-case (syntax y) (quote)
2191 ((quote ()) (syntax x))
2192 (_ (syntax (append x y)))))))
2193 (quasivector
2194 (lambda (x)
2195 (with-syntax ((x x))
2196 (syntax-case (syntax x) (quote list)
2197 ((quote (x ...)) (syntax (quote #(x ...))))
2198 ((list x ...) (syntax (vector x ...)))
2199 (_ (syntax (list->vector x)))))))
2200 (quasi
2201 (lambda (p lev)
2202 (syntax-case p (unquote unquote-splicing quasiquote)
2203 ((unquote p)
2204 (if (= lev 0)
2205 (syntax p)
2206 (quasicons (syntax (quote unquote))
2207 (quasi (syntax (p)) (- lev 1)))))
2208 (((unquote-splicing p) . q)
2209 (if (= lev 0)
2210 (quasiappend (syntax p) (quasi (syntax q) lev))
2211 (quasicons (quasicons (syntax (quote unquote-splicing))
2212 (quasi (syntax (p)) (- lev 1)))
2213 (quasi (syntax q) lev))))
2214 ((quasiquote p)
2215 (quasicons (syntax (quote quasiquote))
2216 (quasi (syntax (p)) (+ lev 1))))
2217 ((p . q)
2218 (quasicons (quasi (syntax p) lev) (quasi (syntax q) lev)))
2219 (#(x ...) (quasivector (quasi (syntax (x ...)) lev)))
2220 (p (syntax (quote p)))))))
2221 (lambda (x)
2222 (syntax-case x ()
2223 ((_ e) (quasi (syntax e) 0))))))
2224
2225(define-syntax include
2226 (lambda (x)
2227 (define read-file
2228 (lambda (fn k)
2229 (let ((p (open-input-file fn)))
2230 (let f ((x (read p)))
2231 (if (eof-object? x)
2232 (begin (close-input-port p) '())
2233 (cons (datum->syntax-object k x)
2234 (f (read p))))))))
2235 (syntax-case x ()
2236 ((k filename)
2237 (let ((fn (syntax-object->datum (syntax filename))))
2238 (with-syntax (((exp ...) (read-file fn (syntax k))))
2239 (syntax (begin exp ...))))))))
2240
2241(define-syntax unquote
2242 (lambda (x)
2243 (syntax-case x ()
2244 ((_ e)
2245 (error 'unquote
2246 "expression ,~s not valid outside of quasiquote"
2247 (syntax-object->datum (syntax e)))))))
2248
2249(define-syntax unquote-splicing
2250 (lambda (x)
2251 (syntax-case x ()
2252 ((_ e)
2253 (error 'unquote-splicing
2254 "expression ,@~s not valid outside of quasiquote"
2255 (syntax-object->datum (syntax e)))))))
2256
2257(define-syntax case
2258 (lambda (x)
2259 (syntax-case x ()
2260 ((_ e m1 m2 ...)
2261 (with-syntax
2262 ((body (let f ((clause (syntax m1)) (clauses (syntax (m2 ...))))
2263 (if (null? clauses)
2264 (syntax-case clause (else)
2265 ((else e1 e2 ...) (syntax (begin e1 e2 ...)))
2266 (((k ...) e1 e2 ...)
2267 (syntax (if (memv t '(k ...)) (begin e1 e2 ...))))
2268 (_ (syntax-error x)))
2269 (with-syntax ((rest (f (car clauses) (cdr clauses))))
2270 (syntax-case clause (else)
2271 (((k ...) e1 e2 ...)
2272 (syntax (if (memv t '(k ...))
2273 (begin e1 e2 ...)
2274 rest)))
2275 (_ (syntax-error x))))))))
2276 (syntax (let ((t e)) body)))))))
2277
2278(define-syntax identifier-syntax
2279 (lambda (x)
2280 (syntax-case x ()
2281 ((_ e)
2282 (syntax
2283 (lambda (x)
2284 (syntax-case x ()
2285 (id
2286 (identifier? (syntax id))
2287 (syntax e))
2288 ((_ x (... ...))
2289 (syntax (e x (... ...)))))))))))