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