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