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