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