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