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