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