0e8747b38b77c1b99c473a1496cb63da60eb49c3
[bpt/guile.git] / module / language / r5rs / psyntax.ss
1 ;;; Portable implementation of syntax-case
2 ;;; Extracted from Chez Scheme Version 6.3
3 ;;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman
4
5 ;;; Copyright (c) 1992-2000 Cadence Research Systems
6 ;;; Permission to copy this software, in whole or in part, to use this
7 ;;; software for any lawful purpose, and to redistribute this software
8 ;;; is granted subject to the restriction that all copies made of this
9 ;;; software must include this copyright notice in full. This software
10 ;;; is provided AS IS, with NO WARRANTY, EITHER EXPRESS OR IMPLIED,
11 ;;; INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
12 ;;; OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE
13 ;;; AUTHORS BE LIABLE FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES OF ANY
14 ;;; NATURE WHATSOEVER.
15
16 ;;; Before attempting to port this code to a new implementation of
17 ;;; Scheme, please read the notes below carefully.
18
19 ;;; This file defines the syntax-case expander, sc-expand, and a set
20 ;;; of associated syntactic forms and procedures. Of these, the
21 ;;; following are documented in The Scheme Programming Language,
22 ;;; Second Edition (R. Kent Dybvig, Prentice Hall, 1996), which can be
23 ;;; found online at http://www.scheme.com. Most are also documented
24 ;;; in the R4RS and draft R5RS.
25 ;;;
26 ;;; bound-identifier=?
27 ;;; datum->syntax-object
28 ;;; define-syntax
29 ;;; fluid-let-syntax
30 ;;; free-identifier=?
31 ;;; generate-temporaries
32 ;;; identifier?
33 ;;; identifier-syntax
34 ;;; let-syntax
35 ;;; letrec-syntax
36 ;;; syntax
37 ;;; syntax-case
38 ;;; syntax-object->datum
39 ;;; syntax-rules
40 ;;; with-syntax
41 ;;;
42 ;;; All standard Scheme syntactic forms are supported by the expander
43 ;;; or syntactic abstractions defined in this file. Only the R4RS
44 ;;; delay is omitted, since its expansion is implementation-dependent.
45
46 ;;; Also defined are three forms that support modules: module, import,
47 ;;; and import-only. These are documented in the Chez Scheme User's
48 ;;; Guide (R. Kent Dybvig, Cadence Research Systems, 1998), which can
49 ;;; also be found online at http://www.scheme.com. They are described
50 ;;; briefly here as well.
51 ;;;
52 ;;; Both are definitions and may appear where and only where other
53 ;;; definitions may appear. modules may be named:
54 ;;;
55 ;;; (module id (ex ...) defn ... init ...)
56 ;;;
57 ;;; or anonymous:
58 ;;;
59 ;;; (module (ex ...) defn ... init ...)
60 ;;;
61 ;;; The latter form is semantically equivalent to:
62 ;;;
63 ;;; (module T (ex ...) defn ... init ...)
64 ;;; (import T)
65 ;;;
66 ;;; where T is a fresh identifier.
67 ;;;
68 ;;; In either form, each of the exports in (ex ...) is either an
69 ;;; identifier or of the form (id ex ...). In the former case, the
70 ;;; single identifier ex is exported. In the latter, the identifier
71 ;;; id is exported and the exports ex ... are "implicitly" exported.
72 ;;; This listing of implicit exports is useful only when id is a
73 ;;; keyword bound to a transformer that expands into references to
74 ;;; the listed implicit exports. In the present implementation,
75 ;;; listing of implicit exports is necessary only for top-level
76 ;;; modules and allows the implementation to avoid placing all
77 ;;; identifiers into the top-level environment where subsequent passes
78 ;;; of the compiler will be unable to deal effectively with them.
79 ;;;
80 ;;; Named modules may be referenced in import statements, which
81 ;;; always take one of the forms:
82 ;;;
83 ;;; (import id)
84 ;;; (import-only id)
85 ;;;
86 ;;; id must name a module. Each exported identifier becomes visible
87 ;;; within the scope of the import form. In the case of import-only,
88 ;;; all other identifiers become invisible in the scope of the
89 ;;; import-only form, except for those established by definitions
90 ;;; that appear textually after the import-only form.
91
92 ;;; The remaining exports are listed below. sc-expand, eval-when, and
93 ;;; syntax-error are described in the Chez Scheme User's Guide.
94 ;;;
95 ;;; (sc-expand datum)
96 ;;; if datum represents a valid expression, sc-expand returns an
97 ;;; expanded version of datum in a core language that includes no
98 ;;; syntactic abstractions. The core language includes begin,
99 ;;; define, if, lambda, letrec, quote, and set!.
100 ;;; (eval-when situations expr ...)
101 ;;; conditionally evaluates expr ... at compile-time or run-time
102 ;;; depending upon situations
103 ;;; (syntax-error object message)
104 ;;; used to report errors found during expansion
105 ;;; ($syntax-dispatch e p)
106 ;;; used by expanded code to handle syntax-case matching
107 ;;; ($sc-put-cte symbol val)
108 ;;; used to establish top-level compile-time (expand-time) bindings.
109
110 ;;; The following nonstandard procedures must be provided by the
111 ;;; implementation for this code to run.
112 ;;;
113 ;;; (void)
114 ;;; returns the implementation's cannonical "unspecified value". The
115 ;;; following usually works:
116 ;;;
117 ;;; (define void (lambda () (if #f #f))).
118 ;;;
119 ;;; (andmap proc list1 list2 ...)
120 ;;; returns true if proc returns true when applied to each element of list1
121 ;;; along with the corresponding elements of list2 .... The following
122 ;;; definition works but does no error checking:
123 ;;;
124 ;;; (define andmap
125 ;;; (lambda (f first . rest)
126 ;;; (or (null? first)
127 ;;; (if (null? rest)
128 ;;; (let andmap ((first first))
129 ;;; (let ((x (car first)) (first (cdr first)))
130 ;;; (if (null? first)
131 ;;; (f x)
132 ;;; (and (f x) (andmap first)))))
133 ;;; (let andmap ((first first) (rest rest))
134 ;;; (let ((x (car first))
135 ;;; (xr (map car rest))
136 ;;; (first (cdr first))
137 ;;; (rest (map cdr rest)))
138 ;;; (if (null? first)
139 ;;; (apply f (cons x xr))
140 ;;; (and (apply f (cons x xr)) (andmap first rest)))))))))
141 ;;;
142 ;;; (ormap proc list1)
143 ;;; returns the first non-false return result of proc applied to
144 ;;; the elements of list1 or false if none. The following definition
145 ;;; works but does no error checking:
146 ;;;
147 ;;; (define ormap
148 ;;; (lambda (proc list1)
149 ;;; (and (not (null? list1))
150 ;;; (or (proc (car list1)) (ormap proc (cdr list1))))))
151 ;;;
152 ;;; The following nonstandard procedures must also be provided by the
153 ;;; implementation for this code to run using the standard portable
154 ;;; hooks and output constructors. They are not used by expanded code,
155 ;;; and so need be present only at expansion time.
156 ;;;
157 ;;; (eval x)
158 ;;; where x is always in the form ("noexpand" expr).
159 ;;; returns the value of expr. the "noexpand" flag is used to tell the
160 ;;; evaluator/expander that no expansion is necessary, since expr has
161 ;;; already been fully expanded to core forms.
162 ;;;
163 ;;; eval will not be invoked during the loading of psyntax.pp. After
164 ;;; psyntax.pp has been loaded, the expansion of any macro definition,
165 ;;; whether local or global, results in a call to eval. If, however,
166 ;;; sc-expand has already been registered as the expander to be used
167 ;;; by eval, and eval accepts one argument, nothing special must be done
168 ;;; to support the "noexpand" flag, since it is handled by sc-expand.
169 ;;;
170 ;;; (error who format-string why what)
171 ;;; where who is either a symbol or #f, format-string is always "~a ~s",
172 ;;; why is always a string, and what may be any object. error should
173 ;;; signal an error with a message something like
174 ;;;
175 ;;; "error in <who>: <why> <what>"
176 ;;;
177 ;;; (gensym)
178 ;;; returns a unique symbol each time it's called. In Chez Scheme, gensym
179 ;;; returns a symbol with a "globally" unique name so that gensyms that
180 ;;; end up in the object code of separately compiled files cannot conflict.
181 ;;; This is necessary only if you intend to support compiled files.
182 ;;;
183 ;;; (putprop symbol key value)
184 ;;; (getprop symbol key)
185 ;;; (remprop symbol key)
186 ;;; key is always a symbol; value may be any object. putprop should
187 ;;; associate the given value with the given symbol and key in some way
188 ;;; that it can be retrieved later with getprop. getprop should return
189 ;;; #f if no value is associated with the given symbol and key. remprop
190 ;;; should remove the association between the given symbol and key.
191
192 ;;; When porting to a new Scheme implementation, you should define the
193 ;;; procedures listed above, load the expanded version of psyntax.ss
194 ;;; (psyntax.pp, which should be available whereever you found
195 ;;; psyntax.ss), and register sc-expand as the current expander (how
196 ;;; you do this depends upon your implementation of Scheme). You may
197 ;;; change the hooks and constructors defined toward the beginning of
198 ;;; the code below, but to avoid bootstrapping problems, do so only
199 ;;; after you have a working version of the expander.
200
201 ;;; Chez Scheme allows the syntactic form (syntax <template>) to be
202 ;;; abbreviated to #'<template>, just as (quote <datum>) may be
203 ;;; abbreviated to '<datum>. The #' syntax makes programs written
204 ;;; using syntax-case shorter and more readable and draws out the
205 ;;; intuitive connection between syntax and quote. If you have access
206 ;;; to the source code of your Scheme system's reader, you might want
207 ;;; to implement this extension.
208
209 ;;; If you find that this code loads or runs slowly, consider
210 ;;; switching to faster hardware or a faster implementation of
211 ;;; Scheme. In Chez Scheme on a 200Mhz Pentium Pro, expanding,
212 ;;; compiling (with full optimization), and loading this file takes
213 ;;; between one and two seconds.
214
215 ;;; In the expander implementation, we sometimes use syntactic abstractions
216 ;;; when procedural abstractions would suffice. For example, we define
217 ;;; top-wrap and top-marked? as
218 ;;; (define-syntax top-wrap (identifier-syntax '((top))))
219 ;;; (define-syntax top-marked?
220 ;;; (syntax-rules ()
221 ;;; ((_ w) (memq 'top (wrap-marks w)))))
222 ;;; rather than
223 ;;; (define top-wrap '((top)))
224 ;;; (define top-marked?
225 ;;; (lambda (w) (memq 'top (wrap-marks w))))
226 ;;; On ther other hand, we don't do this consistently; we define make-wrap,
227 ;;; wrap-marks, and wrap-subst simply as
228 ;;; (define make-wrap cons)
229 ;;; (define wrap-marks car)
230 ;;; (define wrap-subst cdr)
231 ;;; In Chez Scheme, the syntactic and procedural forms of these
232 ;;; abstractions are equivalent, since the optimizer consistently
233 ;;; integrates constants and small procedures. Some Scheme
234 ;;; implementations, however, may benefit from more consistent use
235 ;;; of one form or the other.
236
237
238 ;;; Implementation notes:
239
240 ;;; "begin" is treated as a splicing construct at top level and at
241 ;;; the beginning of bodies. Any sequence of expressions that would
242 ;;; be allowed where the "begin" occurs is allowed.
243
244 ;;; "let-syntax" and "letrec-syntax" are also treated as splicing
245 ;;; constructs, in violation of the R5RS. A consequence is that let-syntax
246 ;;; and letrec-syntax do not create local contours, as do let and letrec.
247 ;;; Although the functionality is greater as it is presently implemented,
248 ;;; we will probably change it to conform to the R5RS. modules provide
249 ;;; similar functionality to nonsplicing letrec-syntax when the latter is
250 ;;; used as a definition.
251
252 ;;; Objects with no standard print syntax, including objects containing
253 ;;; cycles and syntax objects, are allowed in quoted data as long as they
254 ;;; are contained within a syntax form or produced by datum->syntax-object.
255 ;;; Such objects are never copied.
256
257 ;;; When the expander encounters a reference to an identifier that has
258 ;;; no global or lexical binding, it treats it as a global-variable
259 ;;; reference. This allows one to write mutually recursive top-level
260 ;;; definitions, e.g.:
261 ;;;
262 ;;; (define f (lambda (x) (g x)))
263 ;;; (define g (lambda (x) (f x)))
264 ;;;
265 ;;; but may not always yield the intended when the variable in question
266 ;;; is later defined as a keyword.
267
268 ;;; Top-level variable definitions of syntax keywords are permitted.
269 ;;; In order to make this work, top-level define not only produces a
270 ;;; top-level definition in the core language, but also modifies the
271 ;;; compile-time environment (using $sc-put-cte) to record the fact
272 ;;; that the identifier is a variable.
273
274 ;;; Top-level definitions of macro-introduced identifiers are visible
275 ;;; only in code produced by the macro. That is, a binding for a
276 ;;; hidden (generated) identifier is created instead, and subsequent
277 ;;; references within the macro output are renamed accordingly. For
278 ;;; example:
279 ;;;
280 ;;; (define-syntax a
281 ;;; (syntax-rules ()
282 ;;; ((_ var exp)
283 ;;; (begin
284 ;;; (define secret exp)
285 ;;; (define var
286 ;;; (lambda ()
287 ;;; (set! secret (+ secret 17))
288 ;;; secret))))))
289 ;;; (a x 0)
290 ;;; (x) => 17
291 ;;; (x) => 34
292 ;;; secret => Error: variable secret is not bound
293 ;;;
294 ;;; The definition above would fail if the definition for secret
295 ;;; were placed after the definition for var, since the expander would
296 ;;; encounter the references to secret before the definition that
297 ;;; establishes the compile-time map from the identifier secret to
298 ;;; the generated identifier.
299
300 ;;; Identifiers and syntax objects are implemented as vectors for
301 ;;; portability. As a result, it is possible to "forge" syntax
302 ;;; objects.
303
304 ;;; The input to sc-expand may contain "annotations" describing, e.g., the
305 ;;; source file and character position from where each object was read if
306 ;;; it was read from a file. These annotations are handled properly by
307 ;;; sc-expand only if the annotation? hook (see hooks below) is implemented
308 ;;; properly and the operators make-annotation, annotation-expression,
309 ;;; annotation-source, annotation-stripped, and set-annotation-stripped!
310 ;;; are supplied. If annotations are supplied, the proper annotation
311 ;;; source is passed to the various output constructors, allowing
312 ;;; implementations to accurately correlate source and expanded code.
313 ;;; Contact one of the authors for details if you wish to make use of
314 ;;; this feature.
315
316 ;;; Implementation of modules:
317 ;;;
318 ;;; The implementation of modules requires that implicit top-level exports
319 ;;; be listed with the exported macro at some level where both are visible,
320 ;;; e.g.,
321 ;;;
322 ;;; (module M (alpha (beta b))
323 ;;; (module ((alpha a) b)
324 ;;; (define-syntax alpha (identifier-syntax a))
325 ;;; (define a 'a)
326 ;;; (define b 'b))
327 ;;; (define-syntax beta (identifier-syntax b)))
328 ;;;
329 ;;; Listing of implicit imports is not needed for macros that do not make
330 ;;; it out to top level, including all macros that are local to a "body".
331 ;;; (They may be listed in this case, however.) We need this information
332 ;;; for top-level modules since a top-level module expands into a letrec
333 ;;; for non-top-level variables and top-level definitions (assignments) for
334 ;;; top-level variables. Because of the general nature of macro
335 ;;; transformers, we cannot determine the set of implicit exports from the
336 ;;; transformer code, so without the user's help, we'd have to put all
337 ;;; variables at top level.
338 ;;;
339 ;;; Each such top-level identifier is given a generated name (gensym).
340 ;;; When a top-level module is imported at top level, a compile-time
341 ;;; alias is established from the top-level name to the generated name.
342 ;;; The expander follows these aliases transparently. When any module is
343 ;;; imported anywhere other than at top level, the id-var-name of the
344 ;;; import identifier is set to the id-var-name of the export identifier.
345 ;;; Since we can't determine the actual labels for identifiers defined in
346 ;;; top-level modules until we determine which are placed in the letrec
347 ;;; and which make it to top level, we give each an "indirect" label---a
348 ;;; pair whose car will eventually contain the actual label. Import does
349 ;;; not follow the indirect, but id-var-name does.
350 ;;;
351 ;;; All identifiers defined within a local module are folded into the
352 ;;; letrec created for the enclosing body. Visibility is controlled in
353 ;;; this case and for nested top-level modules by introducing a new wrap
354 ;;; for each module.
355
356
357 ;;; Bootstrapping:
358
359 ;;; When changing syntax-object representations, it is necessary to support
360 ;;; both old and new syntax-object representations in id-var-name. It
361 ;;; should be sufficient to recognize old representations and treat
362 ;;; them as not lexically bound.
363
364
365 (let ()
366
367 (define-syntax when
368 (syntax-rules ()
369 ((_ test e1 e2 ...) (if test (begin e1 e2 ...)))))
370 (define-syntax unless
371 (syntax-rules ()
372 ((_ test e1 e2 ...) (when (not test) (begin e1 e2 ...)))))
373 (define-syntax define-structure
374 (lambda (x)
375 (define construct-name
376 (lambda (template-identifier . args)
377 (datum->syntax-object
378 template-identifier
379 (string->symbol
380 (apply string-append
381 (map (lambda (x)
382 (if (string? x)
383 x
384 (symbol->string (syntax-object->datum x))))
385 args))))))
386 (syntax-case x ()
387 ((_ (name id1 ...))
388 (andmap identifier? (syntax (name id1 ...)))
389 (with-syntax
390 ((constructor (construct-name (syntax name) "make-" (syntax name)))
391 (predicate (construct-name (syntax name) (syntax name) "?"))
392 ((access ...)
393 (map (lambda (x) (construct-name x (syntax name) "-" x))
394 (syntax (id1 ...))))
395 ((assign ...)
396 (map (lambda (x)
397 (construct-name x "set-" (syntax name) "-" x "!"))
398 (syntax (id1 ...))))
399 (structure-length
400 (+ (length (syntax (id1 ...))) 1))
401 ((index ...)
402 (let f ((i 1) (ids (syntax (id1 ...))))
403 (if (null? ids)
404 '()
405 (cons i (f (+ i 1) (cdr ids)))))))
406 (syntax (begin
407 (define constructor
408 (lambda (id1 ...)
409 (vector 'name id1 ... )))
410 (define predicate
411 (lambda (x)
412 (and (vector? x)
413 (= (vector-length x) structure-length)
414 (eq? (vector-ref x 0) 'name))))
415 (define access
416 (lambda (x)
417 (vector-ref x index)))
418 ...
419 (define assign
420 (lambda (x update)
421 (vector-set! x index update)))
422 ...)))))))
423
424 (define noexpand "noexpand")
425
426 ;;; hooks to nonportable run-time helpers
427 (begin
428 (define-syntax fx+ (identifier-syntax +))
429 (define-syntax fx- (identifier-syntax -))
430 (define-syntax fx= (identifier-syntax =))
431 (define-syntax fx< (identifier-syntax <))
432
433 (define annotation? (lambda (x) #f))
434
435 (define top-level-eval-hook sc-eval)
436
437 (define local-eval-hook sc-eval)
438
439 (define error-hook (lambda (who why what) (error why what)))
440
441 (define-syntax gensym-hook
442 (syntax-rules ()
443 ((_) (gensym))))
444
445 (define put-global-definition-hook
446 (lambda (symbol val)
447 ($sc-put-cte symbol val)))
448
449 (define get-global-definition-hook
450 (lambda (symbol)
451 (getprop symbol '*sc-expander*)))
452
453 (define get-import-binding
454 (lambda (symbol token)
455 (getprop symbol token)))
456
457 (define generate-id
458 (let ((b (- 127 32 2)))
459 ; session-key should generate a unique integer for each system run
460 ; to support separate compilation
461 (define session-key (lambda () 0))
462 (define make-digit (lambda (x) (integer->char (fx+ x 33))))
463 (define fmt
464 (lambda (n)
465 (let fmt ((n n) (a '()))
466 (if (< n b)
467 (list->string (cons (make-digit n) a))
468 (let ((r (modulo n b)) (rest (quotient n b)))
469 (fmt rest (cons (make-digit r) a)))))))
470 (let ((prefix (fmt (session-key))) (n -1))
471 (lambda (name)
472 (set! n (+ n 1))
473 (let ((newsym (string->symbol (string-append "#" prefix (fmt n)))))
474 newsym)))))
475 )
476
477
478 ;;; output constructors
479 (begin
480 (define-syntax build-application
481 (syntax-rules ()
482 ((_ source fun-exp arg-exps)
483 `(,fun-exp . ,arg-exps))))
484
485 (define-syntax build-conditional
486 (syntax-rules ()
487 ((_ source test-exp then-exp else-exp)
488 `(if ,test-exp ,then-exp ,else-exp))))
489
490 (define-syntax build-lexical-reference
491 (syntax-rules ()
492 ((_ type source var)
493 var)))
494
495 (define-syntax build-lexical-assignment
496 (syntax-rules ()
497 ((_ source var exp)
498 `(set! ,var ,exp))))
499
500 (define-syntax build-global-reference
501 (syntax-rules ()
502 ((_ source var)
503 var)))
504
505 (define-syntax build-global-assignment
506 (syntax-rules ()
507 ((_ source var exp)
508 `(set! ,var ,exp))))
509
510 (define-syntax build-global-definition
511 (syntax-rules ()
512 ((_ source var exp)
513 `(define ,var ,exp))))
514
515 (define-syntax build-module-definition
516 ; should have the effect of a global definition but may not appear at top level
517 (identifier-syntax build-global-assignment))
518
519 (define-syntax build-cte-install
520 ; should build a call that has the same effect as calling the
521 ; global definition hook
522 (syntax-rules ()
523 ((_ sym exp) `($sc-put-cte ',sym ,exp))))
524
525 (define-syntax build-lambda
526 (syntax-rules ()
527 ((_ src vars exp)
528 `(lambda ,vars ,exp))))
529
530 (define-syntax build-primref
531 (syntax-rules ()
532 ((_ src name) name)
533 ((_ src level name) name)))
534
535 (define-syntax build-data
536 (syntax-rules ()
537 ((_ src exp) `',exp)))
538
539 (define build-sequence
540 (lambda (src exps)
541 (if (null? (cdr exps))
542 (car exps)
543 `(begin ,@exps))))
544
545 (define build-letrec
546 (lambda (src vars val-exps body-exp)
547 (if (null? vars)
548 body-exp
549 `(letrec ,(map list vars val-exps) ,body-exp))))
550
551 (define-syntax build-lexical-var
552 (syntax-rules ()
553 ((_ src id) (gensym))))
554
555 (define-syntax self-evaluating?
556 (syntax-rules ()
557 ((_ e)
558 (let ((x e))
559 (or (boolean? x) (number? x) (string? x) (char? x) (null? x))))))
560 )
561
562 (define-structure (syntax-object expression wrap))
563
564 (define-syntax unannotate
565 (syntax-rules ()
566 ((_ x)
567 (let ((e x))
568 (if (annotation? e)
569 (annotation-expression e)
570 e)))))
571
572 (define-syntax no-source (identifier-syntax #f))
573
574 (define source-annotation
575 (lambda (x)
576 (cond
577 ((annotation? x) (annotation-source x))
578 ((syntax-object? x) (source-annotation (syntax-object-expression x)))
579 (else no-source))))
580
581 (define-syntax arg-check
582 (syntax-rules ()
583 ((_ pred? e who)
584 (let ((x e))
585 (if (not (pred? x)) (error-hook who "invalid argument" x))))))
586
587 ;;; compile-time environments
588
589 ;;; wrap and environment comprise two level mapping.
590 ;;; wrap : id --> label
591 ;;; env : label --> <element>
592
593 ;;; environments are represented in two parts: a lexical part and a global
594 ;;; part. The lexical part is a simple list of associations from labels
595 ;;; to bindings. The global part is implemented by
596 ;;; {put,get}-global-definition-hook and associates symbols with
597 ;;; bindings.
598
599 ;;; global (assumed global variable) and displaced-lexical (see below)
600 ;;; do not show up in any environment; instead, they are fabricated by
601 ;;; lookup when it finds no other bindings.
602
603 ;;; <environment> ::= ((<label> . <binding>)*)
604
605 ;;; identifier bindings include a type and a value
606
607 ;;; <binding> ::= (macro . <procedure>) macros
608 ;;; (deferred . <expanded code>) lazy-evaluation of transformers
609 ;;; (core . <procedure>) core forms
610 ;;; (begin) begin
611 ;;; (define) define
612 ;;; (define-syntax) define-syntax
613 ;;; (local-syntax . rec?) let-syntax/letrec-syntax
614 ;;; (eval-when) eval-when
615 ;;; (syntax . (<var> . <level>)) pattern variables
616 ;;; (global . <symbol>) assumed global variable
617 ;;; (lexical . <var>) lexical variables
618 ;;; (displaced-lexical . #f) id-var-name not found in store
619 ;;; <level> ::= <nonnegative integer>
620 ;;; <var> ::= variable returned by build-lexical-var
621
622 ;;; a macro is a user-defined syntactic-form. a core is a system-defined
623 ;;; syntactic form. begin, define, define-syntax, and eval-when are
624 ;;; treated specially since they are sensitive to whether the form is
625 ;;; at top-level and (except for eval-when) can denote valid internal
626 ;;; definitions.
627
628 ;;; a pattern variable is a variable introduced by syntax-case and can
629 ;;; be referenced only within a syntax form.
630
631 ;;; any identifier for which no top-level syntax definition or local
632 ;;; binding of any kind has been seen is assumed to be a global
633 ;;; variable.
634
635 ;;; a lexical variable is a lambda- or letrec-bound variable.
636
637 ;;; a displaced-lexical identifier is a lexical identifier removed from
638 ;;; it's scope by the return of a syntax object containing the identifier.
639 ;;; a displaced lexical can also appear when a letrec-syntax-bound
640 ;;; keyword is referenced on the rhs of one of the letrec-syntax clauses.
641 ;;; a displaced lexical should never occur with properly written macros.
642
643 (define make-binding (lambda (x y) (cons x y)))
644 (define binding-type car)
645 (define binding-value cdr)
646 (define set-binding-type! set-car!)
647 (define set-binding-value! set-cdr!)
648 (define binding? (lambda (x) (and (pair? x) (symbol? (car x)))))
649
650 (define-syntax null-env (identifier-syntax '()))
651
652 (define extend-env
653 (lambda (label binding r)
654 (cons (cons label binding) r)))
655
656 (define extend-env*
657 (lambda (labels bindings r)
658 (if (null? labels)
659 r
660 (extend-env* (cdr labels) (cdr bindings)
661 (extend-env (car labels) (car bindings) r)))))
662
663 (define extend-var-env*
664 ; variant of extend-env* that forms "lexical" binding
665 (lambda (labels vars r)
666 (if (null? labels)
667 r
668 (extend-var-env* (cdr labels) (cdr vars)
669 (extend-env (car labels) (make-binding 'lexical (car vars)) r)))))
670
671 ;;; we use a "macros only" environment in expansion of local macro
672 ;;; definitions so that their definitions can use local macros without
673 ;;; attempting to use other lexical identifiers.
674 ;;;
675 ;;; - can make this null-env if we don't want to allow macros to use other
676 ;;; macros in defining their transformers
677 ;;; - can add a cache here if it pays off
678 (define transformer-env
679 (lambda (r)
680 (if (null? r)
681 '()
682 (let ((a (car r)))
683 (if (eq? (cadr a) 'lexical) ; only strip out lexical so that (transformer x) works
684 (transformer-env (cdr r))
685 (cons a (transformer-env (cdr r))))))))
686
687 (define displaced-lexical-error
688 (lambda (id)
689 (syntax-error id
690 (if (id-var-name id empty-wrap)
691 "identifier out of context"
692 "identifier not visible"))))
693
694 (define lookup*
695 ; x may be a label or a symbol
696 ; although symbols are usually global, we check the environment first
697 ; anyway because a temporary binding may have been established by
698 ; fluid-let-syntax
699 (lambda (x r)
700 (cond
701 ((assq x r) => cdr)
702 ((symbol? x)
703 (or (get-global-definition-hook x) (make-binding 'global x)))
704 (else (make-binding 'displaced-lexical #f)))))
705
706 (define sanitize-binding
707 (lambda (b)
708 (cond
709 ((procedure? b) (make-binding 'macro b))
710 ((binding? b)
711 (case (binding-type b)
712 ((core macro macro!) (and (procedure? (binding-value b)) b))
713 ((module) (and (interface? (binding-value b)) b))
714 (else b)))
715 (else #f))))
716
717 (define lookup
718 (lambda (x r)
719 (define whack-binding!
720 (lambda (b *b)
721 (set-binding-type! b (binding-type *b))
722 (set-binding-value! b (binding-value *b))))
723 (let ((b (lookup* x r)))
724 (case (binding-type b)
725 ; ((*alias) (lookup (id-var-name (binding-value b) empty-wrap) r))
726 ((deferred)
727 (whack-binding! b
728 (let ((*b (local-eval-hook (binding-value b))))
729 (or (sanitize-binding *b)
730 (syntax-error *b "invalid transformer"))))
731 (case (binding-type b)
732 ; ((*alias) (lookup (id-var-name (binding-value b) empty-wrap) r))
733 (else b)))
734 (else b)))))
735
736 (define global-extend
737 (lambda (type sym val)
738 (put-global-definition-hook sym (make-binding type val))))
739
740
741 ;;; Conceptually, identifiers are always syntax objects. Internally,
742 ;;; however, the wrap is sometimes maintained separately (a source of
743 ;;; efficiency and confusion), so that symbols are also considered
744 ;;; identifiers by id?. Externally, they are always wrapped.
745
746 (define nonsymbol-id?
747 (lambda (x)
748 (and (syntax-object? x)
749 (symbol? (unannotate (syntax-object-expression x))))))
750
751 (define id?
752 (lambda (x)
753 (cond
754 ((symbol? x) #t)
755 ((syntax-object? x) (symbol? (unannotate (syntax-object-expression x))))
756 ((annotation? x) (symbol? (annotation-expression x)))
757 (else #f))))
758
759 (define-syntax id-sym-name
760 (syntax-rules ()
761 ((_ e)
762 (let ((x e))
763 (unannotate (if (syntax-object? x) (syntax-object-expression x) x))))))
764
765 (define id-sym-name&marks
766 (lambda (x w)
767 (if (syntax-object? x)
768 (values
769 (unannotate (syntax-object-expression x))
770 (join-marks (wrap-marks w) (wrap-marks (syntax-object-wrap x))))
771 (values (unannotate x) (wrap-marks w)))))
772
773 ;;; syntax object wraps
774
775 ;;; <wrap> ::= ((<mark> ...) . (<subst> ...))
776 ;;; <subst> ::= <ribcage> | <shift>
777 ;;; <ribcage> ::= #((<ex-symname> ...) (<mark> ...) (<label> ...)) ; extensible, for chi-internal/external
778 ;;; | #(#(<symname> ...) #(<mark> ...) #(<label> ...)) ; nonextensible
779 ;;; <ex-symname> ::= <symname> | <import token> | <barrier>
780 ;;; <shift> ::= shift
781 ;;; <barrier> ::= #f ; inserted by import-only
782 ;;; <import token> ::= #<"import-token" <token>>
783 ;;; <token> ::= <generated id>
784
785 (define make-wrap cons)
786 (define wrap-marks car)
787 (define wrap-subst cdr)
788
789 (define-syntax subst-rename? (identifier-syntax vector?))
790 (define-syntax rename-old (syntax-rules () ((_ x) (vector-ref x 0))))
791 (define-syntax rename-new (syntax-rules () ((_ x) (vector-ref x 1))))
792 (define-syntax rename-marks (syntax-rules () ((_ x) (vector-ref x 2))))
793 (define-syntax make-rename
794 (syntax-rules ()
795 ((_ old new marks) (vector old new marks))))
796
797 ;;; labels
798
799 ;;; simple labels must be comparable with "eq?" and distinct from symbols
800 ;;; and pairs.
801
802 ;;; indirect labels, which are implemented as pairs, are used to support
803 ;;; import aliasing for identifiers exported (explictly or implicitly) from
804 ;;; top-level modules. chi-external creates an indirect label for each
805 ;;; defined identifier, import causes the pair to be shared aliases it
806 ;;; establishes, and chi-top-module whacks the pair to hold the top-level
807 ;;; identifier name (symbol) if the id is to be placed at top level, before
808 ;;; expanding the right-hand sides of the definitions in the module.
809
810 (define gen-label
811 (lambda () (string #\i)))
812 (define label?
813 (lambda (x)
814 (or (string? x) ; normal lexical labels
815 (symbol? x) ; global labels (symbolic names)
816 (indirect-label? x))))
817
818 (define gen-labels
819 (lambda (ls)
820 (if (null? ls)
821 '()
822 (cons (gen-label) (gen-labels (cdr ls))))))
823
824 (define gen-indirect-label
825 (lambda () (list (gen-label))))
826
827 (define indirect-label? pair?)
828 (define get-indirect-label car)
829 (define set-indirect-label! set-car!)
830
831 (define-structure (ribcage symnames marks labels))
832 (define-syntax empty-wrap (identifier-syntax '(())))
833
834 (define-syntax top-wrap (identifier-syntax '((top))))
835
836 (define-syntax top-marked?
837 (syntax-rules ()
838 ((_ w) (memq 'top (wrap-marks w)))))
839
840 (define-syntax only-top-marked?
841 (syntax-rules ()
842 ((_ id) (same-marks? (wrap-marks (syntax-object-wrap id)) (wrap-marks top-wrap)))))
843
844 ;;; Marks must be comparable with "eq?" and distinct from pairs and
845 ;;; the symbol top. We do not use integers so that marks will remain
846 ;;; unique even across file compiles.
847
848 (define-syntax the-anti-mark (identifier-syntax #f))
849
850 (define anti-mark
851 (lambda (w)
852 (make-wrap (cons the-anti-mark (wrap-marks w))
853 (cons 'shift (wrap-subst w)))))
854
855 (define-syntax new-mark
856 (syntax-rules ()
857 ((_) (string #\m))))
858
859 (define barrier-marker #f)
860 (module (make-import-token import-token? import-token-key)
861 (define tag 'import-token)
862 (define make-import-token (lambda (x) (cons tag x)))
863 (define import-token? (lambda (x) (and (pair? x) (eq? (car x) tag))))
864 (define import-token-key cdr))
865
866 ;;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
867 ;;; internal definitions, in which the ribcages are built incrementally
868 (define-syntax make-empty-ribcage
869 (syntax-rules ()
870 ((_) (make-ribcage '() '() '()))))
871
872 (define extend-ribcage!
873 ; must receive ids with complete wraps
874 ; ribcage guaranteed to be list-based
875 (lambda (ribcage id label)
876 (set-ribcage-symnames! ribcage
877 (cons (unannotate (syntax-object-expression id))
878 (ribcage-symnames ribcage)))
879 (set-ribcage-marks! ribcage
880 (cons (wrap-marks (syntax-object-wrap id))
881 (ribcage-marks ribcage)))
882 (set-ribcage-labels! ribcage
883 (cons label (ribcage-labels ribcage)))))
884
885 (define extend-ribcage-barrier!
886 ; must receive ids with complete wraps
887 ; ribcage guaranteed to be list-based
888 (lambda (ribcage killer-id)
889 (extend-ribcage-barrier-help! ribcage (syntax-object-wrap killer-id))))
890
891 (define extend-ribcage-barrier-help!
892 (lambda (ribcage wrap)
893 (set-ribcage-symnames! ribcage
894 (cons barrier-marker (ribcage-symnames ribcage)))
895 (set-ribcage-marks! ribcage
896 (cons (wrap-marks wrap) (ribcage-marks ribcage)))))
897
898 (define extend-ribcage-subst!
899 ; ribcage guaranteed to be list-based
900 (lambda (ribcage token)
901 (set-ribcage-symnames! ribcage
902 (cons (make-import-token token) (ribcage-symnames ribcage)))))
903
904 (define lookup-import-binding-name
905 (lambda (sym key marks)
906 (let ((new (get-import-binding sym key)))
907 (and new
908 (let f ((new new))
909 (cond
910 ((pair? new) (or (f (car new)) (f (cdr new))))
911 ((same-marks? marks (wrap-marks (syntax-object-wrap new))) new)
912 (else #f)))))))
913
914 ;;; make-binding-wrap creates vector-based ribcages
915 (define make-binding-wrap
916 (lambda (ids labels w)
917 (if (null? ids)
918 w
919 (make-wrap
920 (wrap-marks w)
921 (cons
922 (let ((labelvec (list->vector labels)))
923 (let ((n (vector-length labelvec)))
924 (let ((symnamevec (make-vector n)) (marksvec (make-vector n)))
925 (let f ((ids ids) (i 0))
926 (if (not (null? ids))
927 (call-with-values
928 (lambda () (id-sym-name&marks (car ids) w))
929 (lambda (symname marks)
930 (vector-set! symnamevec i symname)
931 (vector-set! marksvec i marks)
932 (f (cdr ids) (fx+ i 1))))))
933 (make-ribcage symnamevec marksvec labelvec))))
934 (wrap-subst w))))))
935
936 ;;; make-trimmed-syntax-object is used by make-resolved-interface to support
937 ;;; creation of module export lists whose constituent ids do not contain
938 ;;; unnecessary substitutions or marks.
939 (define make-trimmed-syntax-object
940 (lambda (id)
941 (call-with-values
942 (lambda () (id-var-name&marks id empty-wrap))
943 (lambda (tosym marks)
944 (unless tosym
945 (syntax-error id "identifier not visible for export"))
946 (let ((fromsym (id-sym-name id)))
947 (make-syntax-object fromsym
948 (make-wrap marks
949 (list (make-ribcage (vector fromsym) (vector marks) (vector tosym))))))))))
950
951 ;;; Scheme's append should not copy the first argument if the second is
952 ;;; nil, but it does, so we define a smart version here.
953 (define smart-append
954 (lambda (m1 m2)
955 (if (null? m2)
956 m1
957 (append m1 m2))))
958
959 (define join-wraps
960 (lambda (w1 w2)
961 (let ((m1 (wrap-marks w1)) (s1 (wrap-subst w1)))
962 (if (null? m1)
963 (if (null? s1)
964 w2
965 (make-wrap
966 (wrap-marks w2)
967 (smart-append s1 (wrap-subst w2))))
968 (make-wrap
969 (smart-append m1 (wrap-marks w2))
970 (smart-append s1 (wrap-subst w2)))))))
971
972 (define join-marks
973 (lambda (m1 m2)
974 (smart-append m1 m2)))
975
976 (define same-marks?
977 (lambda (x y)
978 (or (eq? x y)
979 (and (not (null? x))
980 (not (null? y))
981 (eq? (car x) (car y))
982 (same-marks? (cdr x) (cdr y))))))
983
984 (define id-var-name-loc&marks
985 (lambda (id w)
986 (define search
987 (lambda (sym subst marks)
988 (if (null? subst)
989 (values sym marks)
990 (let ((fst (car subst)))
991 (if (eq? fst 'shift)
992 (search sym (cdr subst) (cdr marks))
993 (let ((symnames (ribcage-symnames fst)))
994 (if (vector? symnames)
995 (search-vector-rib sym subst marks symnames fst)
996 (search-list-rib sym subst marks symnames fst))))))))
997 (define search-list-rib
998 (lambda (sym subst marks symnames ribcage)
999 (let f ((symnames symnames) (i 0))
1000 (cond
1001 ((null? symnames) (search sym (cdr subst) marks))
1002 ((and (eq? (car symnames) sym)
1003 (same-marks? marks (list-ref (ribcage-marks ribcage) i)))
1004 (values (list-ref (ribcage-labels ribcage) i) marks))
1005 ((import-token? (car symnames))
1006 (cond
1007 ((lookup-import-binding-name sym (import-token-key (car symnames)) marks) =>
1008 (lambda (id)
1009 (if (symbol? id)
1010 (values id marks)
1011 (id-var-name&marks id empty-wrap)))) ; could be more efficient: new is a resolved id
1012 (else (f (cdr symnames) i))))
1013 ((and (eq? (car symnames) barrier-marker)
1014 (same-marks? marks (list-ref (ribcage-marks ribcage) i)))
1015 (values #f marks))
1016 (else (f (cdr symnames) (fx+ i 1)))))))
1017 (define search-vector-rib
1018 (lambda (sym subst marks symnames ribcage)
1019 (let ((n (vector-length symnames)))
1020 (let f ((i 0))
1021 (cond
1022 ((fx= i n) (search sym (cdr subst) marks))
1023 ((and (eq? (vector-ref symnames i) sym)
1024 (same-marks? marks (vector-ref (ribcage-marks ribcage) i)))
1025 (values (vector-ref (ribcage-labels ribcage) i) marks))
1026 (else (f (fx+ i 1))))))))
1027 (cond
1028 ((symbol? id) (search id (wrap-subst w) (wrap-marks w)))
1029 ((syntax-object? id)
1030 (let ((sym (unannotate (syntax-object-expression id)))
1031 (w1 (syntax-object-wrap id)))
1032 (let ((marks (join-marks (wrap-marks w) (wrap-marks w1))))
1033 (call-with-values (lambda () (search sym (wrap-subst w) marks))
1034 (lambda (new-id marks)
1035 (if (eq? new-id sym)
1036 (search sym (wrap-subst w1) marks)
1037 (values new-id marks)))))))
1038 ((annotation? id) (search (unannotate id) (wrap-subst w) (wrap-marks w)))
1039 (else (error-hook 'id-var-name "invalid id" id)))))
1040
1041 (define id-var-name&marks
1042 ; this version follows indirect labels
1043 (lambda (id w)
1044 (call-with-values
1045 (lambda () (id-var-name-loc&marks id w))
1046 (lambda (label marks)
1047 (values (if (indirect-label? label) (get-indirect-label label) label) marks)))))
1048
1049 (define id-var-name-loc
1050 ; this version doesn't follow indirect labels
1051 (lambda (id w)
1052 (call-with-values
1053 (lambda () (id-var-name-loc&marks id w))
1054 (lambda (label marks) label))))
1055
1056 (define id-var-name
1057 ; this version follows indirect labels
1058 (lambda (id w)
1059 (call-with-values
1060 (lambda () (id-var-name-loc&marks id w))
1061 (lambda (label marks)
1062 (if (indirect-label? label) (get-indirect-label label) label)))))
1063
1064 ;;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
1065 ;;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
1066
1067 (define free-id=?
1068 (lambda (i j)
1069 (and (eq? (id-sym-name i) (id-sym-name j)) ; accelerator
1070 (eq? (id-var-name i empty-wrap) (id-var-name j empty-wrap)))))
1071
1072 (define-syntax literal-id=? (identifier-syntax free-id=?))
1073
1074 ;;; bound-id=? may be passed unwrapped (or partially wrapped) ids as
1075 ;;; long as the missing portion of the wrap is common to both of the ids
1076 ;;; since (bound-id=? x y) iff (bound-id=? (wrap x w) (wrap y w))
1077
1078 (define bound-id=?
1079 (lambda (i j)
1080 (if (and (syntax-object? i) (syntax-object? j))
1081 (and (eq? (unannotate (syntax-object-expression i))
1082 (unannotate (syntax-object-expression j)))
1083 (same-marks? (wrap-marks (syntax-object-wrap i))
1084 (wrap-marks (syntax-object-wrap j))))
1085 (eq? (unannotate i) (unannotate j)))))
1086
1087 ;;; "valid-bound-ids?" returns #t if it receives a list of distinct ids.
1088 ;;; valid-bound-ids? may be passed unwrapped (or partially wrapped) ids
1089 ;;; as long as the missing portion of the wrap is common to all of the
1090 ;;; ids.
1091
1092 (define valid-bound-ids?
1093 (lambda (ids)
1094 (and (let all-ids? ((ids ids))
1095 (or (null? ids)
1096 (and (id? (car ids))
1097 (all-ids? (cdr ids)))))
1098 (distinct-bound-ids? ids))))
1099
1100 ;;; distinct-bound-ids? expects a list of ids and returns #t if there are
1101 ;;; no duplicates. It is quadratic on the length of the id list; long
1102 ;;; lists could be sorted to make it more efficient. distinct-bound-ids?
1103 ;;; may be passed unwrapped (or partially wrapped) ids as long as the
1104 ;;; missing portion of the wrap is common to all of the ids.
1105
1106 (define distinct-bound-ids?
1107 (lambda (ids)
1108 (let distinct? ((ids ids))
1109 (or (null? ids)
1110 (and (not (bound-id-member? (car ids) (cdr ids)))
1111 (distinct? (cdr ids)))))))
1112
1113 (define invalid-ids-error
1114 ; find first bad one and complain about it
1115 (lambda (ids exp class)
1116 (let find ((ids ids) (gooduns '()))
1117 (if (null? ids)
1118 (syntax-error exp) ; shouldn't happen
1119 (if (id? (car ids))
1120 (if (bound-id-member? (car ids) gooduns)
1121 (syntax-error (car ids) "duplicate " class)
1122 (find (cdr ids) (cons (car ids) gooduns)))
1123 (syntax-error (car ids) "invalid " class))))))
1124
1125 (define bound-id-member?
1126 (lambda (x list)
1127 (and (not (null? list))
1128 (or (bound-id=? x (car list))
1129 (bound-id-member? x (cdr list))))))
1130
1131 ;;; wrapping expressions and identifiers
1132
1133 (define wrap
1134 (lambda (x w)
1135 (cond
1136 ((and (null? (wrap-marks w)) (null? (wrap-subst w))) x)
1137 ((syntax-object? x)
1138 (make-syntax-object
1139 (syntax-object-expression x)
1140 (join-wraps w (syntax-object-wrap x))))
1141 ((null? x) x)
1142 (else (make-syntax-object x w)))))
1143
1144 (define source-wrap
1145 (lambda (x w s)
1146 (wrap (if s (make-annotation x s #f) x) w)))
1147
1148 ;;; expanding
1149
1150 (define chi-sequence
1151 (lambda (body r w s)
1152 (build-sequence s
1153 (let dobody ((body body) (r r) (w w))
1154 (if (null? body)
1155 '()
1156 (let ((first (chi (car body) r w)))
1157 (cons first (dobody (cdr body) r w))))))))
1158
1159 (define chi-top-sequence
1160 (lambda (body r w s m esew ribcage)
1161 (build-sequence s
1162 (let dobody ((body body) (r r) (w w) (m m) (esew esew))
1163 (if (null? body)
1164 '()
1165 (let ((first (chi-top (car body) r w m esew ribcage)))
1166 (cons first (dobody (cdr body) r w m esew))))))))
1167
1168 (define chi-when-list
1169 (lambda (e when-list w)
1170 ; when-list is syntax'd version of list of situations
1171 (let f ((when-list when-list) (situations '()))
1172 (if (null? when-list)
1173 situations
1174 (f (cdr when-list)
1175 (cons (let ((x (car when-list)))
1176 (cond
1177 ((literal-id=? x (syntax compile)) 'compile)
1178 ((literal-id=? x (syntax load)) 'load)
1179 ((literal-id=? x (syntax eval)) 'eval)
1180 (else (syntax-error (wrap x w)
1181 "invalid eval-when situation"))))
1182 situations))))))
1183
1184 ;;; syntax-type returns five values: type, value, e, w, and s. The first
1185 ;;; two are described in the table below.
1186 ;;;
1187 ;;; type value explanation
1188 ;;; -------------------------------------------------------------------
1189 ;;; begin none begin keyword
1190 ;;; begin-form none begin expression
1191 ;;; call none any other call
1192 ;;; constant none self-evaluating datum
1193 ;;; core procedure core form (including singleton)
1194 ;;; define none define keyword
1195 ;;; define-form none variable definition
1196 ;;; define-syntax none define-syntax keyword
1197 ;;; define-syntax-form none syntax definition
1198 ;;; displaced-lexical none displaced lexical identifier
1199 ;;; eval-when none eval-when keyword
1200 ;;; eval-when-form none eval-when form
1201 ;;; global name global variable reference
1202 ;;; import none import keyword
1203 ;;; import-form none import form
1204 ;;; lexical name lexical variable reference
1205 ;;; lexical-call name call to lexical variable
1206 ;;; local-syntax rec? letrec-syntax/let-syntax keyword
1207 ;;; local-syntax-form rec? syntax definition
1208 ;;; module none module keyword
1209 ;;; module-form none module definition
1210 ;;; other none anything else
1211 ;;; syntax level pattern variable
1212 ;;;
1213 ;;; For all forms, e is the form, w is the wrap for e. and s is the source.
1214 ;;;
1215 ;;; syntax-type expands macros and unwraps as necessary to get to
1216 ;;; one of the forms above.
1217
1218 (define syntax-type
1219 (lambda (e r w s rib)
1220 (cond
1221 ((symbol? e)
1222 (let* ((n (id-var-name e w))
1223 (b (lookup n r))
1224 (type (binding-type b)))
1225 (case type
1226 ((lexical) (values type (binding-value b) e w s))
1227 ((global) (values type (binding-value b) e w s))
1228 ((macro macro!) (syntax-type (chi-macro (binding-value b) e r w s rib) r empty-wrap #f rib))
1229 (else (values type (binding-value b) e w s)))))
1230 ((pair? e)
1231 (let ((first (car e)))
1232 (if (id? first)
1233 (let* ((n (id-var-name first w))
1234 (b (lookup n r))
1235 (type (binding-type b)))
1236 (case type
1237 ((lexical) (values 'lexical-call (binding-value b) e w s))
1238 ((macro macro!)
1239 (syntax-type (chi-macro (binding-value b) e r w s rib)
1240 r empty-wrap #f rib))
1241 ((core) (values type (binding-value b) e w s))
1242 ((local-syntax)
1243 (values 'local-syntax-form (binding-value b) e w s))
1244 ((begin) (values 'begin-form #f e w s))
1245 ((eval-when) (values 'eval-when-form #f e w s))
1246 ((define) (values 'define-form #f e w s))
1247 ((define-syntax) (values 'define-syntax-form #f e w s))
1248 ((module-key) (values 'module-form #f e w s))
1249 ((import) (values 'import-form (and (binding-value b) (wrap first w)) e w s))
1250 ((set!) (chi-set! e r w s rib))
1251 (else (values 'call #f e w s))))
1252 (values 'call #f e w s))))
1253 ((syntax-object? e)
1254 ;; s can't be valid source if we've unwrapped
1255 (syntax-type (syntax-object-expression e)
1256 r
1257 (join-wraps w (syntax-object-wrap e))
1258 no-source rib))
1259 ((annotation? e)
1260 (syntax-type (annotation-expression e) r w (annotation-source e) rib))
1261 ((self-evaluating? e) (values 'constant #f e w s))
1262 (else (values 'other #f e w s)))))
1263
1264 (define chi-top-expr
1265 (lambda (e r w top-ribcage)
1266 (call-with-values
1267 (lambda () (syntax-type e r w no-source top-ribcage))
1268 (lambda (type value e w s)
1269 (chi-expr type value e r w s)))))
1270
1271 (define chi-top
1272 (lambda (e r w m esew top-ribcage)
1273 (define-syntax eval-if-c&e
1274 (syntax-rules ()
1275 ((_ m e)
1276 (let ((x e))
1277 (if (eq? m 'c&e) (top-level-eval-hook x))
1278 x))))
1279 (call-with-values
1280 (lambda () (syntax-type e r w no-source top-ribcage))
1281 (lambda (type value e w s)
1282 (case type
1283 ((begin-form)
1284 (syntax-case e ()
1285 ((_) (chi-void))
1286 ((_ e1 e2 ...)
1287 (chi-top-sequence (syntax (e1 e2 ...)) r w s m esew top-ribcage))))
1288 ((local-syntax-form)
1289 (chi-local-syntax value e r w s
1290 (lambda (body r w s)
1291 (chi-top-sequence body r w s m esew top-ribcage))))
1292 ((eval-when-form)
1293 (syntax-case e ()
1294 ((_ (x ...) e1 e2 ...)
1295 (let ((when-list (chi-when-list e (syntax (x ...)) w))
1296 (body (syntax (e1 e2 ...))))
1297 (cond
1298 ((eq? m 'e)
1299 (if (memq 'eval when-list)
1300 (chi-top-sequence body r w s 'e '(eval) top-ribcage)
1301 (chi-void)))
1302 ((memq 'load when-list)
1303 (if (or (memq 'compile when-list)
1304 (and (eq? m 'c&e) (memq 'eval when-list)))
1305 (chi-top-sequence body r w s 'c&e '(compile load) top-ribcage)
1306 (if (memq m '(c c&e))
1307 (chi-top-sequence body r w s 'c '(load) top-ribcage)
1308 (chi-void))))
1309 ((or (memq 'compile when-list)
1310 (and (eq? m 'c&e) (memq 'eval when-list)))
1311 (top-level-eval-hook
1312 (chi-top-sequence body r w s 'e '(eval) top-ribcage))
1313 (chi-void))
1314 (else (chi-void)))))))
1315 ((define-syntax-form)
1316 (parse-define-syntax e w s
1317 (lambda (id rhs w)
1318 (let ((id (wrap id w)))
1319 (let ((n (id-var-name id empty-wrap)))
1320 (let ((b (lookup n r)))
1321 (case (binding-type b)
1322 ((displaced-lexical) (displaced-lexical-error id)))))
1323 (ct-eval/residualize m esew
1324 (lambda ()
1325 (build-cte-install
1326 (let ((sym (id-sym-name id)))
1327 (if (only-top-marked? id)
1328 sym
1329 (let ((marks (wrap-marks (syntax-object-wrap id))))
1330 (make-syntax-object sym
1331 (make-wrap marks
1332 (list (make-ribcage (vector sym)
1333 (vector marks) (vector (generate-id sym)))))))))
1334 (chi rhs (transformer-env r) w))))))))
1335 ((define-form)
1336 (parse-define e w s
1337 (lambda (id rhs w)
1338 (let ((id (wrap id w)))
1339 (let ((n (id-var-name id empty-wrap)))
1340 (let ((b (lookup n r)))
1341 (case (binding-type b)
1342 ((displaced-lexical) (displaced-lexical-error id)))))
1343 (let ((sym (id-sym-name id)))
1344 (let ((valsym (if (only-top-marked? id) sym (generate-id sym))))
1345 (build-sequence no-source
1346 (list
1347 (ct-eval/residualize m esew
1348 (lambda ()
1349 (build-cte-install
1350 (if (eq? sym valsym)
1351 sym
1352 (let ((marks (wrap-marks (syntax-object-wrap id))))
1353 (make-syntax-object sym
1354 (make-wrap marks
1355 (list (make-ribcage (vector sym)
1356 (vector marks) (vector valsym)))))))
1357 (build-data no-source (make-binding 'global valsym)))))
1358 (eval-if-c&e m (build-global-definition s valsym (chi rhs r w))))))
1359 )))))
1360 ((module-form)
1361 (let ((r (cons '("top-level module placeholder" . (placeholder)) r))
1362 (ribcage (make-empty-ribcage)))
1363 (parse-module e w s (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))
1364 (lambda (id exports forms)
1365 (if id
1366 (begin
1367 (let ((n (id-var-name id empty-wrap)))
1368 (let ((b (lookup n r)))
1369 (case (binding-type b)
1370 ((displaced-lexical) (displaced-lexical-error (wrap id w))))))
1371 (chi-top-module e r ribcage w s m esew id exports forms))
1372 (chi-top-module e r ribcage w s m esew #f exports forms))))))
1373 ((import-form)
1374 (parse-import e w s
1375 (lambda (mid)
1376 (ct-eval/residualize m esew
1377 (lambda ()
1378 (when value (syntax-error (source-wrap e w s) "not valid at top-level"))
1379 (let ((binding (lookup (id-var-name mid empty-wrap) null-env)))
1380 (case (binding-type binding)
1381 ((module) (do-top-import mid (interface-token (binding-value binding))))
1382 ((displaced-lexical) (displaced-lexical-error mid))
1383 (else (syntax-error mid "import from unknown module")))))))))
1384 (else (eval-if-c&e m (chi-expr type value e r w s))))))))
1385
1386 (define flatten-exports
1387 (lambda (exports)
1388 (let loop ((exports exports) (ls '()))
1389 (if (null? exports)
1390 ls
1391 (loop (cdr exports)
1392 (if (pair? (car exports))
1393 (loop (car exports) ls)
1394 (cons (car exports) ls)))))))
1395
1396
1397 (define-structure (interface exports token))
1398
1399 (define make-trimmed-interface
1400 ; trim out implicit exports
1401 (lambda (exports)
1402 (make-interface
1403 (list->vector (map (lambda (x) (if (pair? x) (car x) x)) exports))
1404 #f)))
1405
1406 (define make-resolved-interface
1407 ; trim out implicit exports & resolve others to actual top-level symbol
1408 (lambda (exports import-token)
1409 (make-interface
1410 (list->vector (map (lambda (x) (make-trimmed-syntax-object (if (pair? x) (car x) x))) exports))
1411 import-token)))
1412
1413 (define-structure (module-binding type id label imps val))
1414
1415 (define chi-top-module
1416 (lambda (e r ribcage w s m esew id exports forms)
1417 (let ((fexports (flatten-exports exports)))
1418 (chi-external ribcage (source-wrap e w s)
1419 (map (lambda (d) (cons r d)) forms) r exports fexports m esew
1420 (lambda (bindings inits)
1421 ; dvs & des: "defined" (letrec-bound) vars & rhs expressions
1422 ; svs & ses: "set!" (top-level) vars & rhs expressions
1423 (let partition ((fexports fexports) (bs bindings) (svs '()) (ses '()) (ctdefs '()))
1424 (if (null? fexports)
1425 ; remaining bindings are either local vars or local macros/modules
1426 (let partition ((bs bs) (dvs '()) (des '()))
1427 (if (null? bs)
1428 (let ((ses (map (lambda (x) (chi (cdr x) (car x) empty-wrap)) ses))
1429 (des (map (lambda (x) (chi (cdr x) (car x) empty-wrap)) des))
1430 (inits (map (lambda (x) (chi (cdr x) (car x) empty-wrap)) inits)))
1431 ; we wait to do this here so that expansion of des & ses use
1432 ; local versions, which in particular, allows us to use macros
1433 ; locally even if esew tells us not to eval them
1434 (for-each (lambda (x)
1435 (apply (lambda (t label sym val)
1436 (when label (set-indirect-label! label sym)))
1437 x))
1438 ctdefs)
1439 (build-sequence no-source
1440 (list (ct-eval/residualize m esew
1441 (lambda ()
1442 (if (null? ctdefs)
1443 (chi-void)
1444 (build-sequence no-source
1445 (map (lambda (x)
1446 (apply (lambda (t label sym val)
1447 (build-cte-install sym
1448 (if (eq? t 'define-syntax-form)
1449 val
1450 (build-data no-source
1451 (make-binding 'module
1452 (make-resolved-interface val sym))))))
1453 x))
1454 ctdefs)))))
1455 (ct-eval/residualize m esew
1456 (lambda ()
1457 (let ((n (if id (id-sym-name id) #f)))
1458 (let* ((token (generate-id n))
1459 (b (build-data no-source
1460 (make-binding 'module
1461 (make-resolved-interface exports token)))))
1462 (if n
1463 (build-cte-install
1464 (if (only-top-marked? id)
1465 n
1466 (let ((marks (wrap-marks (syntax-object-wrap id))))
1467 (make-syntax-object n
1468 (make-wrap marks
1469 (list (make-ribcage (vector n)
1470 (vector marks) (vector (generate-id n))))))))
1471 b)
1472 (let ((n (generate-id 'tmp)))
1473 (build-sequence no-source
1474 (list (build-cte-install n b)
1475 (do-top-import n token)))))))))
1476 ; Some systems complain when undefined variables are assigned.
1477 (build-sequence no-source
1478 (map (lambda (v) (build-global-definition no-source v (chi-void))) svs))
1479 (build-letrec no-source
1480 dvs
1481 des
1482 (build-sequence no-source
1483 (list
1484 (if (null? svs)
1485 (chi-void)
1486 (build-sequence no-source
1487 (map (lambda (v e)
1488 (build-module-definition no-source v e))
1489 svs
1490 ses)))
1491 (if (null? inits)
1492 (chi-void)
1493 (build-sequence no-source inits)))))
1494 (chi-void))))
1495 (let ((b (car bs)))
1496 (case (module-binding-type b)
1497 ((define-form)
1498 (let ((var (gen-var (module-binding-id b))))
1499 (extend-store! r
1500 (get-indirect-label (module-binding-label b))
1501 (make-binding 'lexical var))
1502 (partition (cdr bs) (cons var dvs)
1503 (cons (module-binding-val b) des))))
1504 ((define-syntax-form module-form) (partition (cdr bs) dvs des))
1505 (else (error 'sc-expand-internal "unexpected module binding type"))))))
1506 (let ((id (car fexports)) (fexports (cdr fexports)))
1507 (define pluck-binding
1508 (lambda (id bs succ fail)
1509 (let loop ((bs bs) (new-bs '()))
1510 (if (null? bs)
1511 (fail)
1512 (if (bound-id=? (module-binding-id (car bs)) id)
1513 (succ (car bs) (smart-append (reverse new-bs) (cdr bs)))
1514 (loop (cdr bs) (cons (car bs) new-bs)))))))
1515 (pluck-binding id bs
1516 (lambda (b bs)
1517 (let ((t (module-binding-type b))
1518 (label (module-binding-label b))
1519 (imps (module-binding-imps b)))
1520 (let ((fexports (append imps fexports))
1521 (sym (generate-id (id-sym-name id))))
1522 (case t
1523 ((define-form)
1524 (set-indirect-label! label sym)
1525 (partition fexports bs (cons sym svs)
1526 (cons (module-binding-val b) ses)
1527 ctdefs))
1528 ((define-syntax-form)
1529 (partition fexports bs svs ses
1530 (cons (list t label sym (module-binding-val b)) ctdefs)))
1531 ((module-form)
1532 (let ((exports (module-binding-val b)))
1533 (partition (append (flatten-exports exports) fexports) bs
1534 svs ses
1535 (cons (list t label sym exports) ctdefs))))
1536 (else (error 'sc-expand-internal "unexpected module binding type"))))))
1537 (lambda () (partition fexports bs svs ses ctdefs)))))))))))
1538
1539 (define id-set-diff
1540 (lambda (exports defs)
1541 (cond
1542 ((null? exports) '())
1543 ((bound-id-member? (car exports) defs) (id-set-diff (cdr exports) defs))
1544 (else (cons (car exports) (id-set-diff (cdr exports) defs))))))
1545
1546 (define extend-store!
1547 (lambda (r label binding)
1548 (set-cdr! r (extend-env label binding (cdr r)))))
1549
1550 (define check-module-exports
1551 ; After processing the definitions of a module this is called to verify that the
1552 ; module has defined or imported each exported identifier. Because ids in fexports are
1553 ; wrapped with the given ribcage, they will contain substitutions for anything defined
1554 ; or imported here. These subsitutions can be used by do-import! and do-import-top! to
1555 ; provide access to reexported bindings, for example.
1556 (lambda (source-exp fexports ids)
1557 (define defined?
1558 (lambda (e ids)
1559 (ormap (lambda (x)
1560 (if (interface? x)
1561 (let ((token (interface-token x)))
1562 (if token
1563 (lookup-import-binding-name (id-sym-name e) token (wrap-marks (syntax-object-wrap e)))
1564 (let ((v (interface-exports x)))
1565 (let lp ((i (fx- (vector-length v) 1)))
1566 (and (fx>= i 0)
1567 (or (bound-id=? e (vector-ref v i))
1568 (lp (fx- i 1))))))))
1569 (bound-id=? e x)))
1570 ids)))
1571 (let loop ((fexports fexports) (missing '()))
1572 (if (null? fexports)
1573 (unless (null? missing) (syntax-error missing "missing definition for export(s)"))
1574 (let ((e (car fexports)) (fexports (cdr fexports)))
1575 (if (defined? e ids)
1576 (loop fexports missing)
1577 (loop fexports (cons e missing))))))))
1578
1579 (define check-defined-ids
1580 (lambda (source-exp ls)
1581 (define b-i=?
1582 ; cope with fat-fingered top-level
1583 (lambda (x y)
1584 (if (symbol? x)
1585 (if (symbol? y)
1586 (eq? x y)
1587 (and (eq? x (id-sym-name y))
1588 (same-marks? (wrap-marks (syntax-object-wrap y)) (wrap-marks top-wrap))))
1589 (if (symbol? y)
1590 (and (eq? y (id-sym-name x))
1591 (same-marks? (wrap-marks (syntax-object-wrap x)) (wrap-marks top-wrap)))
1592 (bound-id=? x y)))))
1593 (define vfold
1594 (lambda (v p cls)
1595 (let ((len (vector-length v)))
1596 (let lp ((i 0) (cls cls))
1597 (if (fx= i len)
1598 cls
1599 (lp (fx+ i 1) (p (vector-ref v i) cls)))))))
1600 (define conflicts
1601 (lambda (x y cls)
1602 (if (interface? x)
1603 (if (interface? y)
1604 (call-with-values
1605 (lambda ()
1606 (let ((xe (interface-exports x)) (ye (interface-exports y)))
1607 (if (fx> (vector-length xe) (vector-length ye))
1608 (values x ye)
1609 (values y xe))))
1610 (lambda (iface exports)
1611 (vfold exports (lambda (id cls) (id-iface-conflicts id iface cls)) cls)))
1612 (id-iface-conflicts y x cls))
1613 (if (interface? y)
1614 (id-iface-conflicts x y cls)
1615 (if (b-i=? x y) (cons x cls) cls)))))
1616 (define id-iface-conflicts
1617 (lambda (id iface cls)
1618 (let ((token (interface-token iface)))
1619 (if token
1620 (if (lookup-import-binding-name (id-sym-name id) token
1621 (if (symbol? id)
1622 (wrap-marks top-wrap)
1623 (wrap-marks (syntax-object-wrap id))))
1624 (cons id cls)
1625 cls)
1626 (vfold (interface-exports iface)
1627 (lambda (*id cls) (if (b-i=? *id id) (cons *id cls) cls))
1628 cls)))))
1629 (unless (null? ls)
1630 (let lp ((x (car ls)) (ls (cdr ls)) (cls '()))
1631 (if (null? ls)
1632 (unless (null? cls)
1633 (let ((cls (syntax-object->datum cls)))
1634 (syntax-error source-exp "duplicate definition for "
1635 (symbol->string (car cls))
1636 " in")))
1637 (let lp2 ((ls2 ls) (cls cls))
1638 (if (null? ls2)
1639 (lp (car ls) (cdr ls) cls)
1640 (lp2 (cdr ls2) (conflicts x (car ls2) cls)))))))))
1641
1642 (define chi-external
1643 (lambda (ribcage source-exp body r exports fexports m esew k)
1644 (define return
1645 (lambda (bindings ids inits)
1646 (check-defined-ids source-exp ids)
1647 (check-module-exports source-exp fexports ids)
1648 (k bindings inits)))
1649 (define get-implicit-exports
1650 (lambda (id)
1651 (let f ((exports exports))
1652 (if (null? exports)
1653 '()
1654 (if (and (pair? (car exports)) (bound-id=? id (caar exports)))
1655 (flatten-exports (cdar exports))
1656 (f (cdr exports)))))))
1657 (define update-imp-exports
1658 (lambda (bindings exports)
1659 (let ((exports (map (lambda (x) (if (pair? x) (car x) x)) exports)))
1660 (map (lambda (b)
1661 (let ((id (module-binding-id b)))
1662 (if (not (bound-id-member? id exports))
1663 b
1664 (make-module-binding
1665 (module-binding-type b)
1666 id
1667 (module-binding-label b)
1668 (append (get-implicit-exports id) (module-binding-imps b))
1669 (module-binding-val b)))))
1670 bindings))))
1671 (let parse ((body body) (ids '()) (bindings '()) (inits '()))
1672 (if (null? body)
1673 (return bindings ids inits)
1674 (let ((e (cdar body)) (er (caar body)))
1675 (call-with-values
1676 (lambda () (syntax-type e er empty-wrap no-source ribcage))
1677 (lambda (type value e w s)
1678 (case type
1679 ((define-form)
1680 (parse-define e w s
1681 (lambda (id rhs w)
1682 (let* ((id (wrap id w))
1683 (label (gen-indirect-label))
1684 (imps (get-implicit-exports id)))
1685 (extend-ribcage! ribcage id label)
1686 (parse
1687 (cdr body)
1688 (cons id ids)
1689 (cons (make-module-binding type id label
1690 imps (cons er (wrap rhs w)))
1691 bindings)
1692 inits)))))
1693 ((define-syntax-form)
1694 (parse-define-syntax e w s
1695 (lambda (id rhs w)
1696 (let* ((id (wrap id w))
1697 (label (gen-indirect-label))
1698 (imps (get-implicit-exports id))
1699 (exp (chi rhs (transformer-env er) w)))
1700 ; arrange to evaluate the transformer lazily
1701 (extend-store! r (get-indirect-label label) (cons 'deferred exp))
1702 (extend-ribcage! ribcage id label)
1703 (parse
1704 (cdr body)
1705 (cons id ids)
1706 (cons (make-module-binding type id label imps exp)
1707 bindings)
1708 inits)))))
1709 ((module-form)
1710 (let* ((*ribcage (make-empty-ribcage))
1711 (*w (make-wrap (wrap-marks w) (cons *ribcage (wrap-subst w)))))
1712 (parse-module e w s *w
1713 (lambda (id *exports forms)
1714 (chi-external *ribcage (source-wrap e w s)
1715 (map (lambda (d) (cons er d)) forms)
1716 r *exports (flatten-exports *exports) m esew
1717 (lambda (*bindings *inits)
1718 (let* ((iface (make-trimmed-interface *exports))
1719 (bindings (append (if id *bindings (update-imp-exports *bindings *exports)) bindings))
1720 (inits (append inits *inits)))
1721 (if id
1722 (let ((label (gen-indirect-label))
1723 (imps (get-implicit-exports id)))
1724 (extend-store! r (get-indirect-label label)
1725 (make-binding 'module iface))
1726 (extend-ribcage! ribcage id label)
1727 (parse
1728 (cdr body)
1729 (cons id ids)
1730 (cons (make-module-binding type id label imps *exports) bindings)
1731 inits))
1732 (let ()
1733 (do-import! iface ribcage)
1734 (parse (cdr body) (cons iface ids) bindings inits))))))))))
1735 ((import-form)
1736 (parse-import e w s
1737 (lambda (mid)
1738 (let ((mlabel (id-var-name mid empty-wrap)))
1739 (let ((binding (lookup mlabel r)))
1740 (case (binding-type binding)
1741 ((module)
1742 (let ((iface (binding-value binding)))
1743 (when value (extend-ribcage-barrier! ribcage value))
1744 (do-import! iface ribcage)
1745 (parse
1746 (cdr body)
1747 (cons iface ids)
1748 (update-imp-exports bindings (vector->list (interface-exports iface)))
1749 inits)))
1750 ((displaced-lexical) (displaced-lexical-error mid))
1751 (else (syntax-error mid "import from unknown module"))))))))
1752 ((begin-form)
1753 (syntax-case e ()
1754 ((_ e1 ...)
1755 (parse (let f ((forms (syntax (e1 ...))))
1756 (if (null? forms)
1757 (cdr body)
1758 (cons (cons er (wrap (car forms) w))
1759 (f (cdr forms)))))
1760 ids bindings inits))))
1761 ((local-syntax-form)
1762 (chi-local-syntax value e er w s
1763 (lambda (forms er w s)
1764 (parse (let f ((forms forms))
1765 (if (null? forms)
1766 (cdr body)
1767 (cons (cons er (wrap (car forms) w))
1768 (f (cdr forms)))))
1769 ids bindings inits))))
1770 (else ; found an init expression
1771 (return bindings ids
1772 (append inits (cons (cons er (source-wrap e w s)) (cdr body)))))))))))))
1773
1774 (define vmap
1775 (lambda (fn v)
1776 (do ((i (fx- (vector-length v) 1) (fx- i 1))
1777 (ls '() (cons (fn (vector-ref v i)) ls)))
1778 ((fx< i 0) ls))))
1779
1780 (define vfor-each
1781 (lambda (fn v)
1782 (let ((len (vector-length v)))
1783 (do ((i 0 (fx+ i 1)))
1784 ((fx= i len))
1785 (fn (vector-ref v i))))))
1786
1787 (define do-top-import
1788 (lambda (mid token)
1789 (build-cte-install mid
1790 (build-data no-source
1791 (make-binding 'do-import token)))))
1792
1793 (define ct-eval/residualize
1794 (lambda (m esew thunk)
1795 (case m
1796 ((c) (if (memq 'compile esew)
1797 (let ((e (thunk)))
1798 (top-level-eval-hook e)
1799 (if (memq 'load esew) e (chi-void)))
1800 (if (memq 'load esew) (thunk) (chi-void))))
1801 ((c&e) (let ((e (thunk))) (top-level-eval-hook e) e))
1802 (else (if (memq 'eval esew) (top-level-eval-hook (thunk))) (chi-void)))))
1803
1804 (define chi
1805 (lambda (e r w)
1806 (call-with-values
1807 (lambda () (syntax-type e r w no-source #f))
1808 (lambda (type value e w s)
1809 (chi-expr type value e r w s)))))
1810
1811 (define chi-expr
1812 (lambda (type value e r w s)
1813 (case type
1814 ((lexical)
1815 (build-lexical-reference 'value s value))
1816 ((core) (value e r w s))
1817 ((lexical-call)
1818 (chi-application
1819 (build-lexical-reference 'fun (source-annotation (car e)) value)
1820 e r w s))
1821 ((constant) (build-data s (strip (source-wrap e w s) empty-wrap)))
1822 ((global) (build-global-reference s value))
1823 ((call) (chi-application (chi (car e) r w) e r w s))
1824 ((begin-form)
1825 (syntax-case e ()
1826 ((_ e1 e2 ...) (chi-sequence (syntax (e1 e2 ...)) r w s))))
1827 ((local-syntax-form)
1828 (chi-local-syntax value e r w s chi-sequence))
1829 ((eval-when-form)
1830 (syntax-case e ()
1831 ((_ (x ...) e1 e2 ...)
1832 (let ((when-list (chi-when-list e (syntax (x ...)) w)))
1833 (if (memq 'eval when-list)
1834 (chi-sequence (syntax (e1 e2 ...)) r w s)
1835 (chi-void))))))
1836 ((define-form define-syntax-form module-form import-form)
1837 (syntax-error (source-wrap e w s) "invalid context for definition"))
1838 ((syntax)
1839 (syntax-error (source-wrap e w s)
1840 "reference to pattern variable outside syntax form"))
1841 ((displaced-lexical) (displaced-lexical-error (source-wrap e w s)))
1842 (else (syntax-error (source-wrap e w s))))))
1843
1844 (define chi-application
1845 (lambda (x e r w s)
1846 (syntax-case e ()
1847 ((e0 e1 ...)
1848 (build-application s x
1849 (map (lambda (e) (chi e r w)) (syntax (e1 ...)))))
1850 (_ (syntax-error (source-wrap e w s))))))
1851
1852 (define chi-set!
1853 (lambda (e r w s rib)
1854 (syntax-case e ()
1855 ((_ id val)
1856 (id? (syntax id))
1857 (let ((n (id-var-name (syntax id) w)))
1858 (let ((b (lookup n r)))
1859 (case (binding-type b)
1860 ((macro!)
1861 (let ((id (wrap (syntax id) w)) (val (wrap (syntax val) w)))
1862 (syntax-type (chi-macro (binding-value b)
1863 `(,(syntax set!) ,id ,val)
1864 r empty-wrap s rib) r empty-wrap s rib)))
1865 (else
1866 (values 'core
1867 (lambda (e r w s)
1868 ; repeat lookup in case we were first expression (init) in
1869 ; module or lambda body. we repeat id-var-name as well,
1870 ; although this is only necessary if we allow inits to
1871 ; preced definitions
1872 (let ((val (chi (syntax val) r w))
1873 (n (id-var-name (syntax id) w)))
1874 (let ((b (lookup n r)))
1875 (case (binding-type b)
1876 ((lexical) (build-lexical-assignment s (binding-value b) val))
1877 ((global) (build-global-assignment s (binding-value b) val))
1878 ((displaced-lexical)
1879 (syntax-error (wrap (syntax id) w) "identifier out of context"))
1880 (else (syntax-error (source-wrap e w s)))))))
1881 e w s))))))
1882 (_ (syntax-error (source-wrap e w s))))))
1883
1884 (define chi-macro
1885 (lambda (p e r w s rib)
1886 (define rebuild-macro-output
1887 (lambda (x m)
1888 (cond ((pair? x)
1889 (cons (rebuild-macro-output (car x) m)
1890 (rebuild-macro-output (cdr x) m)))
1891 ((syntax-object? x)
1892 (let ((w (syntax-object-wrap x)))
1893 (let ((ms (wrap-marks w)) (s (wrap-subst w)))
1894 (make-syntax-object (syntax-object-expression x)
1895 (if (and (pair? ms) (eq? (car ms) the-anti-mark))
1896 (make-wrap (cdr ms)
1897 (if rib (cons rib (cdr s)) (cdr s)))
1898 (make-wrap (cons m ms)
1899 (if rib
1900 (cons rib (cons 'shift s))
1901 (cons 'shift s))))))))
1902 ((vector? x)
1903 (let* ((n (vector-length x)) (v (make-vector n)))
1904 (do ((i 0 (fx+ i 1)))
1905 ((fx= i n) v)
1906 (vector-set! v i
1907 (rebuild-macro-output (vector-ref x i) m)))))
1908 ((symbol? x)
1909 (syntax-error (source-wrap e w s)
1910 "encountered raw symbol "
1911 (format "~s" x)
1912 " in output of macro"))
1913 (else x))))
1914 (rebuild-macro-output
1915 (let ((out (p (source-wrap e (anti-mark w) s))))
1916 (if (procedure? out)
1917 (out (lambda (id)
1918 (unless (identifier? id)
1919 (syntax-error id
1920 "environment argument is not an identifier"))
1921 (lookup (id-var-name id empty-wrap) r)))
1922 out))
1923 (new-mark))))
1924
1925 (define chi-body
1926 ;; Here we create the empty wrap and new environment with placeholder
1927 ;; as required by chi-internal. On return we extend the environment
1928 ;; to recognize the var-labels as lexical variables and build a letrec
1929 ;; binding them to the var-vals which we expand here.
1930 (lambda (body outer-form r w)
1931 (let* ((r (cons '("placeholder" . (placeholder)) r))
1932 (ribcage (make-empty-ribcage))
1933 (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w))))
1934 (body (map (lambda (x) (cons r (wrap x w))) body)))
1935 (chi-internal ribcage outer-form body r
1936 (lambda (exprs ids vars vals inits)
1937 (when (null? exprs) (syntax-error outer-form "no expressions in body"))
1938 (build-letrec no-source
1939 vars
1940 (map (lambda (x) (chi (cdr x) (car x) empty-wrap)) vals)
1941 (build-sequence no-source
1942 (map (lambda (x) (chi (cdr x) (car x) empty-wrap)) (append inits exprs)))))))))
1943
1944 (define chi-internal
1945 ;; In processing the forms of the body, we create a new, empty wrap.
1946 ;; This wrap is augmented (destructively) each time we discover that
1947 ;; the next form is a definition. This is done:
1948 ;;
1949 ;; (1) to allow the first nondefinition form to be a call to
1950 ;; one of the defined ids even if the id previously denoted a
1951 ;; definition keyword or keyword for a macro expanding into a
1952 ;; definition;
1953 ;; (2) to prevent subsequent definition forms (but unfortunately
1954 ;; not earlier ones) and the first nondefinition form from
1955 ;; confusing one of the bound identifiers for an auxiliary
1956 ;; keyword; and
1957 ;; (3) so that we do not need to restart the expansion of the
1958 ;; first nondefinition form, which is problematic anyway
1959 ;; since it might be the first element of a begin that we
1960 ;; have just spliced into the body (meaning if we restarted,
1961 ;; we'd really need to restart with the begin or the macro
1962 ;; call that expanded into the begin, and we'd have to give
1963 ;; up allowing (begin <defn>+ <expr>+), which is itself
1964 ;; problematic since we don't know if a begin contains only
1965 ;; definitions until we've expanded it).
1966 ;;
1967 ;; Before processing the body, we also create a new environment
1968 ;; containing a placeholder for the bindings we will add later and
1969 ;; associate this environment with each form. In processing a
1970 ;; let-syntax or letrec-syntax, the associated environment may be
1971 ;; augmented with local keyword bindings, so the environment may
1972 ;; be different for different forms in the body. Once we have
1973 ;; gathered up all of the definitions, we evaluate the transformer
1974 ;; expressions and splice into r at the placeholder the new variable
1975 ;; and keyword bindings. This allows let-syntax or letrec-syntax
1976 ;; forms local to a portion or all of the body to shadow the
1977 ;; definition bindings.
1978 ;;
1979 ;; Subforms of a begin, let-syntax, or letrec-syntax are spliced
1980 ;; into the body.
1981 ;;
1982 ;; outer-form is fully wrapped w/source
1983 (lambda (ribcage source-exp body r k)
1984 (define return
1985 (lambda (exprs ids vars vals inits)
1986 (check-defined-ids source-exp ids)
1987 (k exprs ids vars vals inits)))
1988 (let parse ((body body) (ids '()) (vars '()) (vals '()) (inits '()))
1989 (if (null? body)
1990 (return body ids vars vals inits)
1991 (let ((e (cdar body)) (er (caar body)))
1992 (call-with-values
1993 (lambda () (syntax-type e er empty-wrap no-source ribcage))
1994 (lambda (type value e w s)
1995 (case type
1996 ((define-form)
1997 (parse-define e w s
1998 (lambda (id rhs w)
1999 (let ((id (wrap id w)) (label (gen-label)))
2000 (let ((var (gen-var id)))
2001 (extend-ribcage! ribcage id label)
2002 (extend-store! r label (make-binding 'lexical var))
2003 (parse
2004 (cdr body)
2005 (cons id ids)
2006 (cons var vars)
2007 (cons (cons er (wrap rhs w)) vals)
2008 inits))))))
2009 ((define-syntax-form)
2010 (parse-define-syntax e w s
2011 (lambda (id rhs w)
2012 (let ((id (wrap id w))
2013 (label (gen-label))
2014 (exp (chi rhs (transformer-env er) w)))
2015 (extend-ribcage! ribcage id label)
2016 (extend-store! r label (make-binding 'deferred exp))
2017 (parse (cdr body) (cons id ids) vars vals inits)))))
2018 ((module-form)
2019 (let* ((*ribcage (make-empty-ribcage))
2020 (*w (make-wrap (wrap-marks w) (cons *ribcage (wrap-subst w)))))
2021 (parse-module e w s *w
2022 (lambda (id exports forms)
2023 (chi-internal *ribcage (source-wrap e w s)
2024 (map (lambda (d) (cons er d)) forms) r
2025 (lambda (*body *ids *vars *vals *inits)
2026 ; valid bound ids checked already by chi-internal
2027 (check-module-exports source-exp (flatten-exports exports) *ids)
2028 (let ((iface (make-trimmed-interface exports))
2029 (vars (append *vars vars))
2030 (vals (append *vals vals))
2031 (inits (append inits *inits *body)))
2032 (if id
2033 (let ((label (gen-label)))
2034 (extend-ribcage! ribcage id label)
2035 (extend-store! r label (make-binding 'module iface))
2036 (parse (cdr body) (cons id ids) vars vals inits))
2037 (let ()
2038 (do-import! iface ribcage)
2039 (parse (cdr body) (cons iface ids) vars vals inits))))))))))
2040 ((import-form)
2041 (parse-import e w s
2042 (lambda (mid)
2043 (let ((mlabel (id-var-name mid empty-wrap)))
2044 (let ((binding (lookup mlabel r)))
2045 (case (car binding)
2046 ((module)
2047 (let ((iface (cdr binding)))
2048 (when value (extend-ribcage-barrier! ribcage value))
2049 (do-import! iface ribcage)
2050 (parse (cdr body) (cons iface ids) vars vals inits)))
2051 ((displaced-lexical) (displaced-lexical-error mid))
2052 (else (syntax-error mid "import from unknown module"))))))))
2053 ((begin-form)
2054 (syntax-case e ()
2055 ((_ e1 ...)
2056 (parse (let f ((forms (syntax (e1 ...))))
2057 (if (null? forms)
2058 (cdr body)
2059 (cons (cons er (wrap (car forms) w))
2060 (f (cdr forms)))))
2061 ids vars vals inits))))
2062 ((local-syntax-form)
2063 (chi-local-syntax value e er w s
2064 (lambda (forms er w s)
2065 (parse (let f ((forms forms))
2066 (if (null? forms)
2067 (cdr body)
2068 (cons (cons er (wrap (car forms) w))
2069 (f (cdr forms)))))
2070 ids vars vals inits))))
2071 (else ; found a non-definition
2072 (return (cons (cons er (source-wrap e w s)) (cdr body))
2073 ids vars vals inits))))))))))
2074
2075 (define do-import!
2076 (lambda (interface ribcage)
2077 (let ((token (interface-token interface)))
2078 (if token
2079 (extend-ribcage-subst! ribcage token)
2080 (vfor-each
2081 (lambda (id)
2082 (let ((label1 (id-var-name-loc id empty-wrap)))
2083 (unless label1
2084 (syntax-error id "exported identifier not visible"))
2085 (extend-ribcage! ribcage id label1)))
2086 (interface-exports interface))))))
2087
2088 (define parse-module
2089 (lambda (e w s *w k)
2090 (define listify
2091 (lambda (exports)
2092 (if (null? exports)
2093 '()
2094 (cons (syntax-case (car exports) ()
2095 ((ex ...) (listify (syntax (ex ...))))
2096 (x (if (id? (syntax x))
2097 (wrap (syntax x) *w)
2098 (syntax-error (source-wrap e w s)
2099 "invalid exports list in"))))
2100 (listify (cdr exports))))))
2101 (define return
2102 (lambda (id exports forms)
2103 (k id (listify exports) (map (lambda (x) (wrap x *w)) forms))))
2104 (syntax-case e ()
2105 ((_ (ex ...) form ...)
2106 (return #f (syntax (ex ...)) (syntax (form ...))))
2107 ((_ mid (ex ...) form ...)
2108 (id? (syntax mid))
2109 ; id receives old wrap so it won't be confused with id of same name
2110 ; defined within the module
2111 (return (wrap (syntax mid) w) (syntax (ex ...)) (syntax (form ...))))
2112 (_ (syntax-error (source-wrap e w s))))))
2113
2114 (define parse-import
2115 (lambda (e w s k)
2116 (syntax-case e ()
2117 ((_ mid)
2118 (id? (syntax mid))
2119 (k (wrap (syntax mid) w)))
2120 (_ (syntax-error (source-wrap e w s))))))
2121
2122 (define parse-define
2123 (lambda (e w s k)
2124 (syntax-case e ()
2125 ((_ name val)
2126 (id? (syntax name))
2127 (k (syntax name) (syntax val) w))
2128 ((_ (name . args) e1 e2 ...)
2129 (and (id? (syntax name))
2130 (valid-bound-ids? (lambda-var-list (syntax args))))
2131 (k (wrap (syntax name) w)
2132 (cons (syntax lambda) (wrap (syntax (args e1 e2 ...)) w))
2133 empty-wrap))
2134 ((_ name)
2135 (id? (syntax name))
2136 (k (wrap (syntax name) w) (syntax (void)) empty-wrap))
2137 (_ (syntax-error (source-wrap e w s))))))
2138
2139 (define parse-define-syntax
2140 (lambda (e w s k)
2141 (syntax-case e ()
2142 ((_ name val)
2143 (id? (syntax name))
2144 (k (syntax name) (syntax val) w))
2145 (_ (syntax-error (source-wrap e w s))))))
2146
2147 (define chi-lambda-clause
2148 (lambda (e c r w k)
2149 (syntax-case c ()
2150 (((id ...) e1 e2 ...)
2151 (let ((ids (syntax (id ...))))
2152 (if (not (valid-bound-ids? ids))
2153 (syntax-error e "invalid parameter list in")
2154 (let ((labels (gen-labels ids))
2155 (new-vars (map gen-var ids)))
2156 (k new-vars
2157 (chi-body (syntax (e1 e2 ...))
2158 e
2159 (extend-var-env* labels new-vars r)
2160 (make-binding-wrap ids labels w)))))))
2161 ((ids e1 e2 ...)
2162 (let ((old-ids (lambda-var-list (syntax ids))))
2163 (if (not (valid-bound-ids? old-ids))
2164 (syntax-error e "invalid parameter list in")
2165 (let ((labels (gen-labels old-ids))
2166 (new-vars (map gen-var old-ids)))
2167 (k (let f ((ls1 (cdr new-vars)) (ls2 (car new-vars)))
2168 (if (null? ls1)
2169 ls2
2170 (f (cdr ls1) (cons (car ls1) ls2))))
2171 (chi-body (syntax (e1 e2 ...))
2172 e
2173 (extend-var-env* labels new-vars r)
2174 (make-binding-wrap old-ids labels w)))))))
2175 (_ (syntax-error e)))))
2176
2177 (define chi-local-syntax
2178 (lambda (rec? e r w s k)
2179 (syntax-case e ()
2180 ((_ ((id val) ...) e1 e2 ...)
2181 (let ((ids (syntax (id ...))))
2182 (if (not (valid-bound-ids? ids))
2183 (invalid-ids-error (map (lambda (x) (wrap x w)) ids)
2184 (source-wrap e w s)
2185 "keyword")
2186 (let ((labels (gen-labels ids)))
2187 (let ((new-w (make-binding-wrap ids labels w)))
2188 (k (syntax (e1 e2 ...))
2189 (extend-env*
2190 labels
2191 (let ((w (if rec? new-w w))
2192 (trans-r (transformer-env r)))
2193 (map (lambda (x) (make-binding 'deferred (chi x trans-r w))) (syntax (val ...))))
2194 r)
2195 new-w
2196 s))))))
2197 (_ (syntax-error (source-wrap e w s))))))
2198
2199 (define chi-void
2200 (lambda ()
2201 (build-application no-source (build-primref no-source 'void) '())))
2202
2203 (define ellipsis?
2204 (lambda (x)
2205 (and (nonsymbol-id? x)
2206 (literal-id=? x (syntax (... ...))))))
2207
2208 ;;; data
2209
2210 ;;; strips all annotations from potentially circular reader output
2211
2212 (define strip-annotation
2213 (lambda (x parent)
2214 (cond
2215 ((pair? x)
2216 (let ((new (cons #f #f)))
2217 (when parent (set-annotation-stripped! parent new))
2218 (set-car! new (strip-annotation (car x) #f))
2219 (set-cdr! new (strip-annotation (cdr x) #f))
2220 new))
2221 ((annotation? x)
2222 (or (annotation-stripped x)
2223 (strip-annotation (annotation-expression x) x)))
2224 ((vector? x)
2225 (let ((new (make-vector (vector-length x))))
2226 (when parent (set-annotation-stripped! parent new))
2227 (let loop ((i (- (vector-length x) 1)))
2228 (unless (fx< i 0)
2229 (vector-set! new i (strip-annotation (vector-ref x i) #f))
2230 (loop (fx- i 1))))
2231 new))
2232 (else x))))
2233
2234 ;;; strips syntax-objects down to top-wrap; if top-wrap is layered directly
2235 ;;; on an annotation, strips the annotation as well.
2236 ;;; since only the head of a list is annotated by the reader, not each pair
2237 ;;; in the spine, we also check for pairs whose cars are annotated in case
2238 ;;; we've been passed the cdr of an annotated list
2239
2240 (define strip*
2241 (lambda (x w fn)
2242 (if (top-marked? w)
2243 (fn x)
2244 (let f ((x x))
2245 (cond
2246 ((syntax-object? x)
2247 (strip* (syntax-object-expression x) (syntax-object-wrap x) fn))
2248 ((pair? x)
2249 (let ((a (f (car x))) (d (f (cdr x))))
2250 (if (and (eq? a (car x)) (eq? d (cdr x)))
2251 x
2252 (cons a d))))
2253 ((vector? x)
2254 (let ((old (vector->list x)))
2255 (let ((new (map f old)))
2256 (if (andmap eq? old new) x (list->vector new)))))
2257 (else x))))))
2258
2259 (define strip
2260 (lambda (x w)
2261 (strip* x w
2262 (lambda (x)
2263 (if (or (annotation? x) (and (pair? x) (annotation? (car x))))
2264 (strip-annotation x #f)
2265 x)))))
2266
2267 ;;; lexical variables
2268
2269 (define gen-var
2270 (lambda (id)
2271 (let ((id (if (syntax-object? id) (syntax-object-expression id) id)))
2272 (if (annotation? id)
2273 (build-lexical-var (annotation-source id) (annotation-expression id))
2274 (build-lexical-var no-source id)))))
2275
2276 (define lambda-var-list
2277 (lambda (vars)
2278 (let lvl ((vars vars) (ls '()) (w empty-wrap))
2279 (cond
2280 ((pair? vars) (lvl (cdr vars) (cons (wrap (car vars) w) ls) w))
2281 ((id? vars) (cons (wrap vars w) ls))
2282 ((null? vars) ls)
2283 ((syntax-object? vars)
2284 (lvl (syntax-object-expression vars)
2285 ls
2286 (join-wraps w (syntax-object-wrap vars))))
2287 ((annotation? vars)
2288 (lvl (annotation-expression vars) ls w))
2289 ; include anything else to be caught by subsequent error
2290 ; checking
2291 (else (cons vars ls))))))
2292
2293
2294 ; must precede global-extends
2295
2296 (set! $sc-put-cte
2297 (lambda (id b)
2298 (define put-token
2299 (lambda (id token)
2300 (define cons-id
2301 (lambda (id x)
2302 (if (not x) id (cons id x))))
2303 (define weed
2304 (lambda (id x)
2305 (if (pair? x)
2306 (if (bound-id=? (car x) id) ; could just check same-marks
2307 (weed id (cdr x))
2308 (cons-id (car x) (weed id (cdr x))))
2309 (if (or (not x) (bound-id=? x id))
2310 #f
2311 x))))
2312 (let ((sym (id-sym-name id)))
2313 (let ((x (weed id (getprop sym token))))
2314 (if (and (not x) (symbol? id))
2315 ; don't pollute property list when all we have is a plain
2316 ; top-level binding, since that's what's assumed anyway
2317 (remprop sym token)
2318 (putprop sym token (cons-id id x)))))))
2319 (define sc-put-module
2320 (lambda (exports token)
2321 (vfor-each
2322 (lambda (id) (put-token id token))
2323 exports)))
2324 (define (put-cte id binding)
2325 ;; making assumption here that all macros should be visible to the user and that system
2326 ;; globals don't come through here (primvars.ss sets up their properties)
2327 (let ((sym (if (symbol? id) id (id-var-name id empty-wrap))))
2328 (putprop sym '*sc-expander* binding)))
2329 (let ((binding (or (sanitize-binding b) (error 'define-syntax "invalid transformer ~s" b))))
2330 (case (binding-type binding)
2331 ((module)
2332 (let ((iface (binding-value binding)))
2333 (sc-put-module (interface-exports iface) (interface-token iface)))
2334 (put-cte id binding))
2335 ((do-import) ; fake binding: id is module id, binding-value is import token
2336 (let ((token (binding-value b)))
2337 (let ((b (lookup (id-var-name id empty-wrap) null-env)))
2338 (case (binding-type b)
2339 ((module)
2340 (let ((iface (binding-value b)))
2341 (unless (eq? (interface-token iface) token)
2342 (syntax-error id "import mismatch for module"))
2343 (sc-put-module (interface-exports iface) '*top*)))
2344 (else (syntax-error id "import from unknown module"))))))
2345 (else (put-cte id binding))))))
2346
2347
2348 ;;; core transformers
2349
2350 (global-extend 'local-syntax 'letrec-syntax #t)
2351 (global-extend 'local-syntax 'let-syntax #f)
2352
2353
2354 (global-extend 'core 'fluid-let-syntax
2355 (lambda (e r w s)
2356 (syntax-case e ()
2357 ((_ ((var val) ...) e1 e2 ...)
2358 (valid-bound-ids? (syntax (var ...)))
2359 (let ((names (map (lambda (x) (id-var-name x w)) (syntax (var ...)))))
2360 (for-each
2361 (lambda (id n)
2362 (case (binding-type (lookup n r))
2363 ((displaced-lexical) (displaced-lexical-error (wrap id w)))))
2364 (syntax (var ...))
2365 names)
2366 (chi-body
2367 (syntax (e1 e2 ...))
2368 (source-wrap e w s)
2369 (extend-env*
2370 names
2371 (let ((trans-r (transformer-env r)))
2372 (map (lambda (x) (make-binding 'deferred (chi x trans-r w))) (syntax (val ...))))
2373 r)
2374 w)))
2375 (_ (syntax-error (source-wrap e w s))))))
2376
2377 (global-extend 'core 'quote
2378 (lambda (e r w s)
2379 (syntax-case e ()
2380 ((_ e) (build-data s (strip (syntax e) w)))
2381 (_ (syntax-error (source-wrap e w s))))))
2382
2383 (global-extend 'core 'syntax
2384 (let ()
2385 (define gen-syntax
2386 (lambda (src e r maps ellipsis?)
2387 (if (id? e)
2388 (let ((label (id-var-name e empty-wrap)))
2389 (let ((b (lookup label r)))
2390 (if (eq? (binding-type b) 'syntax)
2391 (call-with-values
2392 (lambda ()
2393 (let ((var.lev (binding-value b)))
2394 (gen-ref src (car var.lev) (cdr var.lev) maps)))
2395 (lambda (var maps) (values `(ref ,var) maps)))
2396 (if (ellipsis? e)
2397 (syntax-error src "misplaced ellipsis in syntax form")
2398 (values `(quote ,e) maps)))))
2399 (syntax-case e ()
2400 ((dots e)
2401 (ellipsis? (syntax dots))
2402 (gen-syntax src (syntax e) r maps (lambda (x) #f)))
2403 ((x dots . y)
2404 ; this could be about a dozen lines of code, except that we
2405 ; choose to handle (syntax (x ... ...)) forms
2406 (ellipsis? (syntax dots))
2407 (let f ((y (syntax y))
2408 (k (lambda (maps)
2409 (call-with-values
2410 (lambda ()
2411 (gen-syntax src (syntax x) r
2412 (cons '() maps) ellipsis?))
2413 (lambda (x maps)
2414 (if (null? (car maps))
2415 (syntax-error src
2416 "extra ellipsis in syntax form")
2417 (values (gen-map x (car maps))
2418 (cdr maps))))))))
2419 (syntax-case y ()
2420 ((dots . y)
2421 (ellipsis? (syntax dots))
2422 (f (syntax y)
2423 (lambda (maps)
2424 (call-with-values
2425 (lambda () (k (cons '() maps)))
2426 (lambda (x maps)
2427 (if (null? (car maps))
2428 (syntax-error src
2429 "extra ellipsis in syntax form")
2430 (values (gen-mappend x (car maps))
2431 (cdr maps))))))))
2432 (_ (call-with-values
2433 (lambda () (gen-syntax src y r maps ellipsis?))
2434 (lambda (y maps)
2435 (call-with-values
2436 (lambda () (k maps))
2437 (lambda (x maps)
2438 (values (gen-append x y) maps)))))))))
2439 ((x . y)
2440 (call-with-values
2441 (lambda () (gen-syntax src (syntax x) r maps ellipsis?))
2442 (lambda (x maps)
2443 (call-with-values
2444 (lambda () (gen-syntax src (syntax y) r maps ellipsis?))
2445 (lambda (y maps) (values (gen-cons x y) maps))))))
2446 (#(e1 e2 ...)
2447 (call-with-values
2448 (lambda ()
2449 (gen-syntax src (syntax (e1 e2 ...)) r maps ellipsis?))
2450 (lambda (e maps) (values (gen-vector e) maps))))
2451 (_ (values `(quote ,e) maps))))))
2452
2453 (define gen-ref
2454 (lambda (src var level maps)
2455 (if (fx= level 0)
2456 (values var maps)
2457 (if (null? maps)
2458 (syntax-error src "missing ellipsis in syntax form")
2459 (call-with-values
2460 (lambda () (gen-ref src var (fx- level 1) (cdr maps)))
2461 (lambda (outer-var outer-maps)
2462 (let ((b (assq outer-var (car maps))))
2463 (if b
2464 (values (cdr b) maps)
2465 (let ((inner-var (gen-var 'tmp)))
2466 (values inner-var
2467 (cons (cons (cons outer-var inner-var)
2468 (car maps))
2469 outer-maps)))))))))))
2470
2471 (define gen-mappend
2472 (lambda (e map-env)
2473 `(apply (primitive append) ,(gen-map e map-env))))
2474
2475 (define gen-map
2476 (lambda (e map-env)
2477 (let ((formals (map cdr map-env))
2478 (actuals (map (lambda (x) `(ref ,(car x))) map-env)))
2479 (cond
2480 ((eq? (car e) 'ref)
2481 ; identity map equivalence:
2482 ; (map (lambda (x) x) y) == y
2483 (car actuals))
2484 ((andmap
2485 (lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
2486 (cdr e))
2487 ; eta map equivalence:
2488 ; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
2489 `(map (primitive ,(car e))
2490 ,@(map (let ((r (map cons formals actuals)))
2491 (lambda (x) (cdr (assq (cadr x) r))))
2492 (cdr e))))
2493 (else `(map (lambda ,formals ,e) ,@actuals))))))
2494
2495 (define gen-cons
2496 (lambda (x y)
2497 (case (car y)
2498 ((quote)
2499 (if (eq? (car x) 'quote)
2500 `(quote (,(cadr x) . ,(cadr y)))
2501 (if (eq? (cadr y) '())
2502 `(list ,x)
2503 `(cons ,x ,y))))
2504 ((list) `(list ,x ,@(cdr y)))
2505 (else `(cons ,x ,y)))))
2506
2507 (define gen-append
2508 (lambda (x y)
2509 (if (equal? y '(quote ()))
2510 x
2511 `(append ,x ,y))))
2512
2513 (define gen-vector
2514 (lambda (x)
2515 (cond
2516 ((eq? (car x) 'list) `(vector ,@(cdr x)))
2517 ((eq? (car x) 'quote) `(quote #(,@(cadr x))))
2518 (else `(list->vector ,x)))))
2519
2520
2521 (define regen
2522 (lambda (x)
2523 (case (car x)
2524 ((ref) (build-lexical-reference 'value no-source (cadr x)))
2525 ((primitive) (build-primref no-source (cadr x)))
2526 ((quote) (build-data no-source (cadr x)))
2527 ((lambda) (build-lambda no-source (cadr x) (regen (caddr x))))
2528 ((map) (let ((ls (map regen (cdr x))))
2529 (build-application no-source
2530 (if (fx= (length ls) 2)
2531 (build-primref no-source 'map)
2532 ; really need to do our own checking here
2533 (build-primref no-source 2 'map)) ; require error check
2534 ls)))
2535 (else (build-application no-source
2536 (build-primref no-source (car x))
2537 (map regen (cdr x)))))))
2538
2539 (lambda (e r w s)
2540 (let ((e (source-wrap e w s)))
2541 (syntax-case e ()
2542 ((_ x)
2543 (call-with-values
2544 (lambda () (gen-syntax e (syntax x) r '() ellipsis?))
2545 (lambda (e maps) (regen e))))
2546 (_ (syntax-error e)))))))
2547
2548
2549 (global-extend 'core 'lambda
2550 (lambda (e r w s)
2551 (syntax-case e ()
2552 ((_ . c)
2553 (chi-lambda-clause (source-wrap e w s) (syntax c) r w
2554 (lambda (vars body) (build-lambda s vars body)))))))
2555
2556
2557 (global-extend 'core 'letrec
2558 (lambda (e r w s)
2559 (syntax-case e ()
2560 ((_ ((id val) ...) e1 e2 ...)
2561 (let ((ids (syntax (id ...))))
2562 (if (not (valid-bound-ids? ids))
2563 (invalid-ids-error (map (lambda (x) (wrap x w)) ids)
2564 (source-wrap e w s) "bound variable")
2565 (let ((labels (gen-labels ids))
2566 (new-vars (map gen-var ids)))
2567 (let ((w (make-binding-wrap ids labels w))
2568 (r (extend-var-env* labels new-vars r)))
2569 (build-letrec s
2570 new-vars
2571 (map (lambda (x) (chi x r w)) (syntax (val ...)))
2572 (chi-body (syntax (e1 e2 ...)) (source-wrap e w s) r w)))))))
2573 (_ (syntax-error (source-wrap e w s))))))
2574
2575 (global-extend 'core 'if
2576 (lambda (e r w s)
2577 (syntax-case e ()
2578 ((_ test then)
2579 (build-conditional s
2580 (chi (syntax test) r w)
2581 (chi (syntax then) r w)
2582 (chi-void)))
2583 ((_ test then else)
2584 (build-conditional s
2585 (chi (syntax test) r w)
2586 (chi (syntax then) r w)
2587 (chi (syntax else) r w)))
2588 (_ (syntax-error (source-wrap e w s))))))
2589
2590
2591
2592 (global-extend 'set! 'set! '())
2593
2594 (global-extend 'begin 'begin '())
2595
2596 (global-extend 'module-key 'module '())
2597 (global-extend 'import 'import #f)
2598 (global-extend 'import 'import-only #t)
2599
2600 (global-extend 'define 'define '())
2601
2602 (global-extend 'define-syntax 'define-syntax '())
2603
2604 (global-extend 'eval-when 'eval-when '())
2605
2606 (global-extend 'core 'syntax-case
2607 (let ()
2608 (define convert-pattern
2609 ; accepts pattern & keys
2610 ; returns syntax-dispatch pattern & ids
2611 (lambda (pattern keys)
2612 (let cvt ((p pattern) (n 0) (ids '()))
2613 (if (id? p)
2614 (if (bound-id-member? p keys)
2615 (values (vector 'free-id p) ids)
2616 (values 'any (cons (cons p n) ids)))
2617 (syntax-case p ()
2618 ((x dots)
2619 (ellipsis? (syntax dots))
2620 (call-with-values
2621 (lambda () (cvt (syntax x) (fx+ n 1) ids))
2622 (lambda (p ids)
2623 (values (if (eq? p 'any) 'each-any (vector 'each p))
2624 ids))))
2625 ((x . y)
2626 (call-with-values
2627 (lambda () (cvt (syntax y) n ids))
2628 (lambda (y ids)
2629 (call-with-values
2630 (lambda () (cvt (syntax x) n ids))
2631 (lambda (x ids)
2632 (values (cons x y) ids))))))
2633 (() (values '() ids))
2634 (#(x ...)
2635 (call-with-values
2636 (lambda () (cvt (syntax (x ...)) n ids))
2637 (lambda (p ids) (values (vector 'vector p) ids))))
2638 (x (values (vector 'atom (strip p empty-wrap)) ids)))))))
2639
2640 (define build-dispatch-call
2641 (lambda (pvars exp y r)
2642 (let ((ids (map car pvars)) (levels (map cdr pvars)))
2643 (let ((labels (gen-labels ids)) (new-vars (map gen-var ids)))
2644 (build-application no-source
2645 (build-primref no-source 'apply)
2646 (list (build-lambda no-source new-vars
2647 (chi exp
2648 (extend-env*
2649 labels
2650 (map (lambda (var level)
2651 (make-binding 'syntax `(,var . ,level)))
2652 new-vars
2653 (map cdr pvars))
2654 r)
2655 (make-binding-wrap ids labels empty-wrap)))
2656 y))))))
2657
2658 (define gen-clause
2659 (lambda (x keys clauses r pat fender exp)
2660 (call-with-values
2661 (lambda () (convert-pattern pat keys))
2662 (lambda (p pvars)
2663 (cond
2664 ((not (distinct-bound-ids? (map car pvars)))
2665 (invalid-ids-error (map car pvars) pat "pattern variable"))
2666 ((not (andmap (lambda (x) (not (ellipsis? (car x)))) pvars))
2667 (syntax-error pat
2668 "misplaced ellipsis in syntax-case pattern"))
2669 (else
2670 (let ((y (gen-var 'tmp)))
2671 ; fat finger binding and references to temp variable y
2672 (build-application no-source
2673 (build-lambda no-source (list y)
2674 (let-syntax ((y (identifier-syntax
2675 (build-lexical-reference 'value no-source y))))
2676 (build-conditional no-source
2677 (syntax-case fender ()
2678 (#t y)
2679 (_ (build-conditional no-source
2680 y
2681 (build-dispatch-call pvars fender y r)
2682 (build-data no-source #f))))
2683 (build-dispatch-call pvars exp y r)
2684 (gen-syntax-case x keys clauses r))))
2685 (list (if (eq? p 'any)
2686 (build-application no-source
2687 (build-primref no-source 'list)
2688 (list (build-lexical-reference no-source 'value x)))
2689 (build-application no-source
2690 (build-primref no-source '$syntax-dispatch)
2691 (list (build-lexical-reference no-source 'value x)
2692 (build-data no-source p)))))))))))))
2693
2694 (define gen-syntax-case
2695 (lambda (x keys clauses r)
2696 (if (null? clauses)
2697 (build-application no-source
2698 (build-primref no-source 'syntax-error)
2699 (list (build-lexical-reference 'value no-source x)))
2700 (syntax-case (car clauses) ()
2701 ((pat exp)
2702 (if (and (id? (syntax pat))
2703 (not (bound-id-member? (syntax pat) keys))
2704 (not (ellipsis? (syntax pat))))
2705 (let ((label (gen-label))
2706 (var (gen-var (syntax pat))))
2707 (build-application no-source
2708 (build-lambda no-source (list var)
2709 (chi (syntax exp)
2710 (extend-env label (make-binding 'syntax `(,var . 0)) r)
2711 (make-binding-wrap (syntax (pat))
2712 (list label) empty-wrap)))
2713 (list (build-lexical-reference 'value no-source x))))
2714 (gen-clause x keys (cdr clauses) r
2715 (syntax pat) #t (syntax exp))))
2716 ((pat fender exp)
2717 (gen-clause x keys (cdr clauses) r
2718 (syntax pat) (syntax fender) (syntax exp)))
2719 (_ (syntax-error (car clauses) "invalid syntax-case clause"))))))
2720
2721 (lambda (e r w s)
2722 (let ((e (source-wrap e w s)))
2723 (syntax-case e ()
2724 ((_ val (key ...) m ...)
2725 (if (andmap (lambda (x) (and (id? x) (not (ellipsis? x))))
2726 (syntax (key ...)))
2727 (let ((x (gen-var 'tmp)))
2728 ; fat finger binding and references to temp variable x
2729 (build-application s
2730 (build-lambda no-source (list x)
2731 (gen-syntax-case x
2732 (syntax (key ...)) (syntax (m ...))
2733 r))
2734 (list (chi (syntax val) r empty-wrap))))
2735 (syntax-error e "invalid literals list in"))))))))
2736
2737 ;;; The portable sc-expand seeds chi-top's mode m with 'e (for
2738 ;;; evaluating) and esew (which stands for "eval syntax expanders
2739 ;;; when") with '(eval). In Chez Scheme, m is set to 'c instead of e
2740 ;;; if we are compiling a file, and esew is set to
2741 ;;; (eval-syntactic-expanders-when), which defaults to the list
2742 ;;; '(compile load eval). This means that, by default, top-level
2743 ;;; syntactic definitions are evaluated immediately after they are
2744 ;;; expanded, and the expanded definitions are also residualized into
2745 ;;; the object file if we are compiling a file.
2746 (set! sc-expand
2747 (let ((user-ribcage
2748 (let ((ribcage (make-empty-ribcage)))
2749 (extend-ribcage-subst! ribcage '*top*)
2750 ribcage)))
2751 (let ((user-top-wrap
2752 (make-wrap (wrap-marks top-wrap)
2753 (cons user-ribcage (wrap-subst top-wrap)))))
2754 (lambda (x)
2755 (let ((m 'e)
2756 (esew '(eval)))
2757 (if (and (pair? x) (equal? (car x) noexpand))
2758 (cadr x)
2759 (chi-top x null-env user-top-wrap m esew user-ribcage)))))))
2760
2761 (set! identifier?
2762 (lambda (x)
2763 (nonsymbol-id? x)))
2764
2765 (set! datum->syntax-object
2766 (lambda (id datum)
2767 (arg-check nonsymbol-id? id 'datum->syntax-object)
2768 (make-syntax-object datum (syntax-object-wrap id))))
2769
2770 (set! syntax-object->datum
2771 ; accepts any object, since syntax objects may consist partially
2772 ; or entirely of unwrapped, nonsymbolic data
2773 (lambda (x)
2774 (strip x empty-wrap)))
2775
2776 (set! generate-temporaries
2777 (lambda (ls)
2778 (arg-check list? ls 'generate-temporaries)
2779 (map (lambda (x) (wrap (gensym-hook) top-wrap)) ls)))
2780
2781 (set! free-identifier=?
2782 (lambda (x y)
2783 (arg-check nonsymbol-id? x 'free-identifier=?)
2784 (arg-check nonsymbol-id? y 'free-identifier=?)
2785 (free-id=? x y)))
2786
2787 (set! bound-identifier=?
2788 (lambda (x y)
2789 (arg-check nonsymbol-id? x 'bound-identifier=?)
2790 (arg-check nonsymbol-id? y 'bound-identifier=?)
2791 (bound-id=? x y)))
2792
2793
2794 (set! syntax-error
2795 (lambda (object . messages)
2796 (for-each (lambda (x) (arg-check string? x 'syntax-error)) messages)
2797 (let ((message (if (null? messages)
2798 "invalid syntax"
2799 (apply string-append messages))))
2800 (error-hook #f message (strip object empty-wrap)))))
2801
2802 ;;; syntax-dispatch expects an expression and a pattern. If the expression
2803 ;;; matches the pattern a list of the matching expressions for each
2804 ;;; "any" is returned. Otherwise, #f is returned. (This use of #f will
2805 ;;; not work on r4rs implementations that violate the ieee requirement
2806 ;;; that #f and () be distinct.)
2807
2808 ;;; The expression is matched with the pattern as follows:
2809
2810 ;;; pattern: matches:
2811 ;;; () empty list
2812 ;;; any anything
2813 ;;; (<pattern>1 . <pattern>2) (<pattern>1 . <pattern>2)
2814 ;;; each-any (any*)
2815 ;;; #(free-id <key>) <key> with free-identifier=?
2816 ;;; #(each <pattern>) (<pattern>*)
2817 ;;; #(vector <pattern>) (list->vector <pattern>)
2818 ;;; #(atom <object>) <object> with "equal?"
2819
2820 ;;; Vector cops out to pair under assumption that vectors are rare. If
2821 ;;; not, should convert to:
2822 ;;; #(vector <pattern>*) #(<pattern>*)
2823
2824 (let ()
2825
2826 (define match-each
2827 (lambda (e p w)
2828 (cond
2829 ((annotation? e)
2830 (match-each (annotation-expression e) p w))
2831 ((pair? e)
2832 (let ((first (match (car e) p w '())))
2833 (and first
2834 (let ((rest (match-each (cdr e) p w)))
2835 (and rest (cons first rest))))))
2836 ((null? e) '())
2837 ((syntax-object? e)
2838 (match-each (syntax-object-expression e)
2839 p
2840 (join-wraps w (syntax-object-wrap e))))
2841 (else #f))))
2842
2843 (define match-each-any
2844 (lambda (e w)
2845 (cond
2846 ((annotation? e)
2847 (match-each-any (annotation-expression e) w))
2848 ((pair? e)
2849 (let ((l (match-each-any (cdr e) w)))
2850 (and l (cons (wrap (car e) w) l))))
2851 ((null? e) '())
2852 ((syntax-object? e)
2853 (match-each-any (syntax-object-expression e)
2854 (join-wraps w (syntax-object-wrap e))))
2855 (else #f))))
2856
2857 (define match-empty
2858 (lambda (p r)
2859 (cond
2860 ((null? p) r)
2861 ((eq? p 'any) (cons '() r))
2862 ((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
2863 ((eq? p 'each-any) (cons '() r))
2864 (else
2865 (case (vector-ref p 0)
2866 ((each) (match-empty (vector-ref p 1) r))
2867 ((free-id atom) r)
2868 ((vector) (match-empty (vector-ref p 1) r)))))))
2869
2870 (define match*
2871 (lambda (e p w r)
2872 (cond
2873 ((null? p) (and (null? e) r))
2874 ((pair? p)
2875 (and (pair? e) (match (car e) (car p) w
2876 (match (cdr e) (cdr p) w r))))
2877 ((eq? p 'each-any)
2878 (let ((l (match-each-any e w))) (and l (cons l r))))
2879 (else
2880 (case (vector-ref p 0)
2881 ((each)
2882 (if (null? e)
2883 (match-empty (vector-ref p 1) r)
2884 (let ((l (match-each e (vector-ref p 1) w)))
2885 (and l
2886 (let collect ((l l))
2887 (if (null? (car l))
2888 r
2889 (cons (map car l) (collect (map cdr l)))))))))
2890 ((free-id) (and (id? e) (literal-id=? (wrap e w) (vector-ref p 1)) r))
2891 ((atom) (and (equal? (vector-ref p 1) (strip e w)) r))
2892 ((vector)
2893 (and (vector? e)
2894 (match (vector->list e) (vector-ref p 1) w r))))))))
2895
2896 (define match
2897 (lambda (e p w r)
2898 (cond
2899 ((not r) #f)
2900 ((eq? p 'any) (cons (wrap e w) r))
2901 ((syntax-object? e)
2902 (match*
2903 (unannotate (syntax-object-expression e))
2904 p
2905 (join-wraps w (syntax-object-wrap e))
2906 r))
2907 (else (match* (unannotate e) p w r)))))
2908
2909 (set! $syntax-dispatch
2910 (lambda (e p)
2911 (cond
2912 ((eq? p 'any) (list e))
2913 ((syntax-object? e)
2914 (match* (unannotate (syntax-object-expression e))
2915 p (syntax-object-wrap e) '()))
2916 (else (match* (unannotate e) p empty-wrap '())))))
2917 ))
2918
2919
2920 (define-syntax with-syntax
2921 (lambda (x)
2922 (syntax-case x ()
2923 ((_ () e1 e2 ...)
2924 (syntax (begin e1 e2 ...)))
2925 ((_ ((out in)) e1 e2 ...)
2926 (syntax (syntax-case in () (out (begin e1 e2 ...)))))
2927 ((_ ((out in) ...) e1 e2 ...)
2928 (syntax (syntax-case (list in ...) ()
2929 ((out ...) (begin e1 e2 ...))))))))
2930
2931 (define-syntax syntax-rules
2932 (lambda (x)
2933 (syntax-case x ()
2934 ((_ (k ...) ((keyword . pattern) template) ...)
2935 (syntax (lambda (x)
2936 (syntax-case x (k ...)
2937 ((dummy . pattern) (syntax template))
2938 ...)))))))
2939
2940 (define-syntax or
2941 (lambda (x)
2942 (syntax-case x ()
2943 ((_) (syntax #f))
2944 ((_ e) (syntax e))
2945 ((_ e1 e2 e3 ...)
2946 (syntax (let ((t e1)) (if t t (or e2 e3 ...))))))))
2947
2948 (define-syntax and
2949 (lambda (x)
2950 (syntax-case x ()
2951 ((_ e1 e2 e3 ...) (syntax (if e1 (and e2 e3 ...) #f)))
2952 ((_ e) (syntax e))
2953 ((_) (syntax #t)))))
2954
2955 (define-syntax let
2956 (lambda (x)
2957 (syntax-case x ()
2958 ((_ ((x v) ...) e1 e2 ...)
2959 (andmap identifier? (syntax (x ...)))
2960 (syntax ((lambda (x ...) e1 e2 ...) v ...)))
2961 ((_ f ((x v) ...) e1 e2 ...)
2962 (andmap identifier? (syntax (f x ...)))
2963 (syntax ((letrec ((f (lambda (x ...) e1 e2 ...))) f)
2964 v ...))))))
2965
2966 (define-syntax let*
2967 (lambda (x)
2968 (syntax-case x ()
2969 ((let* ((x v) ...) e1 e2 ...)
2970 (andmap identifier? (syntax (x ...)))
2971 (let f ((bindings (syntax ((x v) ...))))
2972 (if (null? bindings)
2973 (syntax (let () e1 e2 ...))
2974 (with-syntax ((body (f (cdr bindings)))
2975 (binding (car bindings)))
2976 (syntax (let (binding) body)))))))))
2977
2978 (define-syntax cond
2979 (lambda (x)
2980 (syntax-case x ()
2981 ((_ m1 m2 ...)
2982 (let f ((clause (syntax m1)) (clauses (syntax (m2 ...))))
2983 (if (null? clauses)
2984 (syntax-case clause (else =>)
2985 ((else e1 e2 ...) (syntax (begin e1 e2 ...)))
2986 ((e0) (syntax (let ((t e0)) (if t t))))
2987 ((e0 => e1) (syntax (let ((t e0)) (if t (e1 t)))))
2988 ((e0 e1 e2 ...) (syntax (if e0 (begin e1 e2 ...))))
2989 (_ (syntax-error x)))
2990 (with-syntax ((rest (f (car clauses) (cdr clauses))))
2991 (syntax-case clause (else =>)
2992 ((e0) (syntax (let ((t e0)) (if t t rest))))
2993 ((e0 => e1) (syntax (let ((t e0)) (if t (e1 t) rest))))
2994 ((e0 e1 e2 ...) (syntax (if e0 (begin e1 e2 ...) rest)))
2995 (_ (syntax-error x))))))))))
2996
2997 (define-syntax do
2998 (lambda (orig-x)
2999 (syntax-case orig-x ()
3000 ((_ ((var init . step) ...) (e0 e1 ...) c ...)
3001 (with-syntax (((step ...)
3002 (map (lambda (v s)
3003 (syntax-case s ()
3004 (() v)
3005 ((e) (syntax e))
3006 (_ (syntax-error orig-x))))
3007 (syntax (var ...))
3008 (syntax (step ...)))))
3009 (syntax-case (syntax (e1 ...)) ()
3010 (() (syntax (let doloop ((var init) ...)
3011 (if (not e0)
3012 (begin c ... (doloop step ...))))))
3013 ((e1 e2 ...)
3014 (syntax (let doloop ((var init) ...)
3015 (if e0
3016 (begin e1 e2 ...)
3017 (begin c ... (doloop step ...))))))))))))
3018
3019 (define-syntax quasiquote
3020 (letrec
3021 ; these are here because syntax-case uses literal-identifier=?,
3022 ; and we want the more precise free-identifier=?
3023 ((isquote? (lambda (x)
3024 (and (identifier? x)
3025 (free-identifier=? x (syntax quote)))))
3026 (islist? (lambda (x)
3027 (and (identifier? x)
3028 (free-identifier=? x (syntax list)))))
3029 (iscons? (lambda (x)
3030 (and (identifier? x)
3031 (free-identifier=? x (syntax cons)))))
3032 (quote-nil? (lambda (x)
3033 (syntax-case x ()
3034 ((quote? ()) (isquote? (syntax quote?)))
3035 (_ #f))))
3036 (quasilist*
3037 (lambda (x y)
3038 (let f ((x x))
3039 (if (null? x)
3040 y
3041 (quasicons (car x) (f (cdr x)))))))
3042 (quasicons
3043 (lambda (x y)
3044 (with-syntax ((x x) (y y))
3045 (syntax-case (syntax y) ()
3046 ((quote? dy)
3047 (isquote? (syntax quote?))
3048 (syntax-case (syntax x) ()
3049 ((quote? dx)
3050 (isquote? (syntax quote?))
3051 (syntax (quote (dx . dy))))
3052 (_ (if (null? (syntax dy))
3053 (syntax (list x))
3054 (syntax (cons x y))))))
3055 ((listp . stuff)
3056 (islist? (syntax listp))
3057 (syntax (list x . stuff)))
3058 (else (syntax (cons x y)))))))
3059 (quasiappend
3060 (lambda (x y)
3061 (let ((ls (let f ((x x))
3062 (if (null? x)
3063 (if (quote-nil? y)
3064 '()
3065 (list y))
3066 (if (quote-nil? (car x))
3067 (f (cdr x))
3068 (cons (car x) (f (cdr x))))))))
3069 (cond
3070 ((null? ls) (syntax (quote ())))
3071 ((null? (cdr ls)) (car ls))
3072 (else (with-syntax (((p ...) ls))
3073 (syntax (append p ...))))))))
3074 (quasivector
3075 (lambda (x)
3076 (with-syntax ((pat-x x))
3077 (syntax-case (syntax pat-x) ()
3078 ((quote? (x ...))
3079 (isquote? (syntax quote?))
3080 (syntax (quote #(x ...))))
3081 (_ (let f ((x x) (k (lambda (ls) `(,(syntax vector) ,@ls))))
3082 (syntax-case x ()
3083 ((quote? (x ...))
3084 (isquote? (syntax quote?))
3085 (k (syntax ((quote x) ...))))
3086 ((listp x ...)
3087 (islist? (syntax listp))
3088 (k (syntax (x ...))))
3089 ((cons? x y)
3090 (iscons? (syntax cons?))
3091 (f (syntax y) (lambda (ls) (k (cons (syntax x) ls)))))
3092 (else
3093 (syntax (list->vector pat-x))))))))))
3094 (quasi
3095 (lambda (p lev)
3096 (syntax-case p (unquote unquote-splicing quasiquote)
3097 ((unquote p)
3098 (if (= lev 0)
3099 (syntax p)
3100 (quasicons (syntax (quote unquote))
3101 (quasi (syntax (p)) (- lev 1)))))
3102 (((unquote p ...) . q)
3103 (if (= lev 0)
3104 (quasilist* (syntax (p ...)) (quasi (syntax q) lev))
3105 (quasicons (quasicons (syntax (quote unquote))
3106 (quasi (syntax (p ...)) (- lev 1)))
3107 (quasi (syntax q) lev))))
3108 (((unquote-splicing p ...) . q)
3109 (if (= lev 0)
3110 (quasiappend (syntax (p ...)) (quasi (syntax q) lev))
3111 (quasicons (quasicons (syntax (quote unquote-splicing))
3112 (quasi (syntax (p ...)) (- lev 1)))
3113 (quasi (syntax q) lev))))
3114 ((quasiquote p)
3115 (quasicons (syntax (quote quasiquote))
3116 (quasi (syntax (p)) (+ lev 1))))
3117 ((p . q)
3118 (quasicons (quasi (syntax p) lev) (quasi (syntax q) lev)))
3119 (#(x ...) (quasivector (quasi (syntax (x ...)) lev)))
3120 (p (syntax (quote p)))))))
3121 (lambda (x)
3122 (syntax-case x ()
3123 ((_ e) (quasi (syntax e) 0))))))
3124
3125 (define-syntax include
3126 (lambda (x)
3127 (define read-file
3128 (lambda (fn k)
3129 (let ((p (open-input-file fn)))
3130 (let f ()
3131 (let ((x (read p)))
3132 (if (eof-object? x)
3133 (begin (close-input-port p) '())
3134 (cons (datum->syntax-object k x) (f))))))))
3135 (syntax-case x ()
3136 ((k filename)
3137 (let ((fn (syntax-object->datum (syntax filename))))
3138 (with-syntax (((exp ...) (read-file fn (syntax k))))
3139 (syntax (begin exp ...))))))))
3140
3141 (define-syntax unquote
3142 (lambda (x)
3143 (syntax-case x ()
3144 ((_ e ...)
3145 (syntax-error x
3146 "expression not valid outside of quasiquote")))))
3147
3148 (define-syntax unquote-splicing
3149 (lambda (x)
3150 (syntax-case x ()
3151 ((_ e ...)
3152 (syntax-error x
3153 "expression not valid outside of quasiquote")))))
3154
3155 (define-syntax case
3156 (lambda (x)
3157 (syntax-case x ()
3158 ((_ e m1 m2 ...)
3159 (with-syntax
3160 ((body (let f ((clause (syntax m1)) (clauses (syntax (m2 ...))))
3161 (if (null? clauses)
3162 (syntax-case clause (else)
3163 ((else e1 e2 ...) (syntax (begin e1 e2 ...)))
3164 (((k ...) e1 e2 ...)
3165 (syntax (if (memv t '(k ...)) (begin e1 e2 ...))))
3166 (_ (syntax-error x)))
3167 (with-syntax ((rest (f (car clauses) (cdr clauses))))
3168 (syntax-case clause (else)
3169 (((k ...) e1 e2 ...)
3170 (syntax (if (memv t '(k ...))
3171 (begin e1 e2 ...)
3172 rest)))
3173 (_ (syntax-error x))))))))
3174 (syntax (let ((t e)) body)))))))
3175
3176 (define-syntax identifier-syntax
3177 (lambda (x)
3178 (syntax-case x (set!)
3179 ((_ e)
3180 (syntax
3181 (lambda (x)
3182 (syntax-case x ()
3183 (id
3184 (identifier? (syntax id))
3185 (syntax e))
3186 ((_ x (... ...))
3187 (syntax (e x (... ...))))))))
3188 ((_ (id exp1) ((set! var val) exp2))
3189 (and (identifier? (syntax id)) (identifier? (syntax var)))
3190 (syntax
3191 (cons 'macro!
3192 (lambda (x)
3193 (syntax-case x (set!)
3194 ((set! var val) (syntax exp2))
3195 ((id x (... ...)) (syntax (exp1 x (... ...))))
3196 (id (identifier? (syntax id)) (syntax exp1))))))))))
3197