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