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