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