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