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