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